web-dev-qa-db-ja.com

React css遷移が正しく機能しません

CSSトランジションを使用してReactアプリを作成しました。ただし、これらのトランジションは一部のコンポーネントで正しく動作しません。 my app では、上方向への移動はうまく機能し、下方向への移動はアニメーションなしで即座に移動します(両方ともアニメーションとともに移動する必要があります)。

そこで使用したCSSを次に示します。

div.canvas {
    position: absolute;
    top: 90px;
    left: 60px;
    width: 640px;
    height: 480px;
    border: 1px solid #999;
    background: white;

}

div.canvas-rect {
    position: relative;
    margin-left: 20px;
    margin-top: 10px;
    height: 20px;
    background: green;

    transition: all 1s linear;
    -moz-transition: all 1s linear; /* Firefox 4 */
    -webkit-transition: all 1s linear; /* Safari 和 Chrome */
    -o-transition: all 1s linear; /* Opera */

}

更新しました:

また、問題を示すために codepen.ioプロジェクト を作成しました。このデモプロジェクトの完全なコードが含まれています。

ログエントリをcomponentDidUpdatecomponentDidMountおよびcomponentWillUnmountメソッドに追加して、これらのコンポーネントが再作成または更新されているかどうかを表示しようとしました。 (再作成または削除されません)毎秒。

22
cmal

まあ、私もこの問題を抱えているので私が賞金を始めた後、私は最終的に問題と思われるものを見つけました。

絶対位置(またはあなたの場合のように相対)を使用している場合、毎回リスト全体を再レンダリングすると、ReactはDOM内の要素を並べ替えます、要素は再作成されず、更新されるだけです)しかし、これにより遷移に問題が発生します...明らかに、遷移の実行中に要素を移動すると、アニメーションが切れてしまいます。

したがって、絶対位置を使用する場合の重要な概念は、要素のコンテナーを1回(この場合はdivのみ)レンダリングし、新しい順序に基づいて内部コンテンツのみを変更することです。さらに要素を追加する必要がある場合は、最後に追加します。

私が言っていることを反映するように、私はあなたのコードペンを修正しました。私の例は4つのアドホックdivを作成したばかりなので非常に愚かですが、必要なだけコンテナを作成しますが、毎回コンテナを再作成するマップを使用しないでください。そうしないと、トランジションがカットされます。

https://codepen.io/damianmr/pen/boEmmy?editors=011

const ArrList = ({
  arr
}) => {
  return (
    <div style={{position: 'relative'}}>
      <div className={`element element-${arr[0]} index-${arr[0]}`}>{arr[0]}</div>
      <div className={`element element-${arr[1]} index-${arr[1]}`}>{arr[1]}</div>  
      <div className={`element element-${arr[2]} index-${arr[2]}`}>{arr[2]}</div>  
      <div className={`element element-${arr[3]} index-${arr[3]}`}>{arr[3]}</div>  
    </div>
  );
}

したがって、問題は基本的に、コンテナの静的リストを作成する方法と、最初のコンテナがデータの最初の要素、2番目のコンテナが2番目の要素などをレンダリングするようにそのリストを反復処理する方法です。

それが役立つことを願って、この問題も私を夢中にさせました! :)

20
damianmr

私はこれが事実ではないことを知っていますが、ここに着いたのでReact css transition does not work correctly、私はただ共有したかった:

render内の矢印関数を使用して要素を作成するの場合、新しいコンポーネントが常に作成されるため、適切にアニメーション化されません。外部で関数を作成し、「render」で呼び出す必要があります。

3
carla

仮想DOMから要素を削除する場合、reactはそのコンテンツを更新するため、アニメーションは表示されません。できることは、 react-transition-group ORを使用することです。イベントが呼び出されたら、domを更新する前にx ms待機するようアプリに指示しますOR可視性を使用して切り替えますDOMから完全に削除する代わりに、非表示にして表示します。

2
Iruss

indexをキーとして使用して、Reactをだますことができます。el、およびindexを開始位置(インデックス)および終了として考える場合位置(el)、遷移の終わりまでに要素が古い終了位置に移動し、そこに達すると新しい開始位置に引き継がれ、(インデックス)が新しいセットアップに一致するように切り替えられます。 reactの要素にkeyを設定すると、仮想DOMは常に同じ要素であると解釈します。そのため、インデックスを一般的に「id」として設定するのは正しいです。

Index/elを切り替える(および要素の位置を絶対に設定する)だけで実用的な例を作成しました。

const {combineReducers, createStore} = Redux;
const { Provider, connect } = ReactRedux;

const ArrList = ({
  arr
}) => (
  <div>{
  arr.map((el, index)=>
          <div
            key={""+index}
            className={`element element-${el}` + ` index-${el}`}
            >
            {el}
          </div>) }
  </div>
)
      
const mapStateToArrList = (state) => {
  return {
    arr: state.appReducer.arr
  }
};

const App = connect(mapStateToArrList, null)(ArrList);

const initialState = {
  arr: [1, 2, 3, 4]
}

const appReducer = (state = initialState, action) => {
  switch(action.type) {
    case "tick":
      return {
        ...state,
        arr: _.shuffle(state.arr)
      }
    default:
      return state
   }
}

const reducer = combineReducers({
  appReducer
})


const store = createStore(reducer)

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
)

const dispatcher = () => {
  store.dispatch({
     type: "tick"
  })
  setTimeout(dispatcher, 1000)
}

dispatcher()
.element {
    position: absolute;
    height: 20px;
    background: green;
    margin-left: 20px;
    margin-top: 20px;

    text-align: right;
    color: white;
    line-height: 20px;

    transition: all 1s ease-in;
    -moz-transition: all 1s ease-in; /* Firefox 4 */
    -webkit-transition: all 1s ease-in; /* Safari 和 Chrome */
    -o-transition: all 1s ease-in; /* Opera */

}

.element-1 {
    width: 20px;
}

.element-2 {
    width: 40px;
}

.element-3 {
    width: 60px;
}

.element-4 {
    width: 80px;
}

.index-1 {
  top: 20px;
}

.index-2 {
  top: 40px;
}

.index-3 {
  top: 60px;
}

.index-4 {
  top: 80px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/3.7.2/redux.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/5.0.6/react-redux.js"></script>

<div id="root"></div>
2
LPL

毎回DOM要素を再作成しました。
収集キー値を定義する必要があります。キー値を変更しました'' + elから'' + index

<div key={'' + index} className={'element element-' + el + ' index-' + index} >

cssプロパティのみを変更するだけです:)

1
panghea