Coffee Break Point

Reactのレンダリング順について

useEffect系はコンポネント順ではない

考えてみると当たり前だが、順番的には子コンポーネントのレンダリング準備が整ってから親コンポーネントのレンダリングに取り掛かる


なので、親のuseEffectやuseLayoutEffectは子コンポーネントのそれらが終えてから実行される



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 import React, {useState, useLayoutEffect, createContext, useContext} from "https://cdn.skypack.dev/react@17.0.1"; import * as ReactDOM from "https://cdn.skypack.dev/react-dom@17.0.1"; const StateContext = createContext({}) const App = () => { const [state, setState] = useState([]) useLayoutEffect(() => { console.log("parent layout effect") setState((currentState) => [...currentState, "parent"]) }, []) const stateContextProps = { state: state, setState: setState } console.log("parent") console.log(state) return ( <StateContext.Provider value={stateContextProps}> <ChildComponent name="child1"/> <ChildComponent name="child2"/> <ChildComponent name="child3"/> </StateContext.Provider> ) } const ChildComponent = ({name}) => { const stateContext = useContext(StateContext) useLayoutEffect(() => { console.log(name + " layout effect") stateContext.setState((currentState) => [...currentState, name]) }, []) console.log(name) return ( <div> {name} </div> ) } ReactDOM.render(<App />, document.querySelector('#app'))

↓ 実行ログ


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 "parent" // [object Array] (0) [] "child1" "child2" "child3" "child1 layout effect" "child2 layout effect" "child3 layout effect" "parent layout effect" "parent" // [object Array] (4) ["child1","child2","child3","parent"] "child1" "child2" "child3"

実行順は親→子コンポーネント(親のreturn内で初めて子コンポーネントが呼ばれるので)
にもかかわらず、useLayoutEffectの順は子→親。


親は子の最後にuseEffectされる点に注意

useContextでsetStateを渡して子コンポーネント内で親のstateを操作するような場合、親の操作するタイミングには注意する必要があるようです。

例えば親→子の順にstateに値を追加していきたい場合は、親が最後に呼ばれるので、下記のように親を先頭に追加するよう記載する必要があります。


1 2 3 4 useLayoutEffect(() => { console.log("parent layout effect") setState((currentState) => ["parent", ...currentState]) }, [])

↓ 実行ログ


1 2 // [object Array] (4) ["parent","child1","child2","child3"]

← Back to home

©from-garage 2022 All Rights Reserved.

powered by