ReactフックsetState()を使用して、コンポーネントが受け取る小道具を使用して状態を設定しようとしています。以下のコードを使用してみました:
import React,{useState , useEffect} from 'react';
const Persons = (props) => {
// console.log(props.name);
const [nameState , setNameState] = useState(props)
console.log(nameState.name);
console.log(props.name);
return (
<div>
<p>My name is {props.name} and my age is {props.age}</p>
<p>My profession is {props.profession}</p>
</div>
)
}
export default Persons;
問題は、コンポーネントのロード時に状態が設定されていることです。しかし、新しい小道具を受け取ったとき、状態は更新されていません。この場合、状態を更新するにはどうすればよいですか?前もって感謝します。
useState
hooks関数の引数は、プロップが変更されるたびにではなく、一度だけ使用されます。 componentWillReceiveProps/getDerivedStateFromProps
機能と呼ぶものを実装するには、useEffect
フックを使用する必要があります
import React,{useState , useEffect} from 'react';
const Persons = (props) => {
const [nameState , setNameState] = useState(props)
useEffect(() => {
setNameState(props);
}, [props])
return (
<div>
<p>My name is {props.name} and my age is {props.age}</p>
<p>My profession is {props.profession}</p>
</div>
)
}
export default Persons;
そのためには、useEffect
を使用して、コードを次のようにする必要があります。プロが変更されなかった場合に再度レンダリングしないようにするには、まずuseEffectを確認してから、プロップを現在の変数に設定する必要があります。
import React, { useState, useEffect } from "react";
const Persons = props => {
// console.log(props.name);
const [nameState, setNameState] = useState(props);
console.log(nameState.name);
console.log(props.name);
useEffect(
() => {
if (nameState !== props.name) {
setNameState(props.name);
}
},
[nameState]
);
return (
<div>
<p>
My name is {props.name} and my age is {props.age}
</p>
<p>My profession is {props.profession}</p>
</div>
);
};
export default Persons;
この一般的な考えはフックに入れることができます:
export function useStateFromProp(initialValue) {
const [value, setValue] = useState(initialValue);
useEffect(() => setValue(initialValue), [initialValue]);
return [value, setValue];
}
function MyComponent({ value: initialValue }) {
const [value, setValue] = useStateFromProp(initialValue);
return (...);
}
import React, { useState, useEffect } from "react";
const Persons = props => {
// console.log(props.name);
const [nameState, setNameState] = useState(props);
console.log(nameState.name);
console.log(props.name);
useEffect(
() => {
if (nameState !== props) {
setNameState(props);
}
},
[nameState]
);
return (
<div>
<p>
My name is {props.name} and my age is {props.age}
</p>
<p>My profession is {props.profession}</p>
</div>
);
};
export default Persons;
Hooks反応ドキュメントに従って、propsが更新されているとき、またはコンポーネントの更新がそこにあるときは常に、useEffectが呼び出されます。したがって、useStateを更新する前に状態を確認してから、値が更新され、継続的に再レンダリングされないようにする必要があります。
useState
に渡される初期状態は 最初のレンダリング中にのみ使用 であり、無視されるため、それ以上の状態の更新を受け取ることはありません。さらに、派生状態を更新するときにuseEffect
は必要ありません。
const Persons = props => {
const [nameState, setNameState] = React.useState(props.name);
// Here, we update derived state without useEffect
if (props.name !== nameState) setNameState(props.name);
return (
<p>
<p>Persons name</p>
<div>{nameState} (derived state)</div>
<div>{props.name} (props)</div>
</p>
);
};
const App = () => {
const [personName, setPersonName] = React.useState("Lui");
const changeName = () => setPersonName(personName === "Lukas" ? "Lui" : "Lukas");
return (
<div>
<Persons name={personName} />
<button onClick={changeName}>Change props</button>
</div>
);
};
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.0/umd/react.production.min.js" integrity="sha256-32Gmw5rBDXyMjg/73FgpukoTZdMrxuYW7tj8adbN8z4=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.0/umd/react-dom.production.min.js" integrity="sha256-bjQ42ac3EN0GqK40pC9gGi/YixvKyZ24qMP/9HiGW7w=" crossorigin="anonymous"></script>
<div id="root"></div>
から React docs :
レンダリング中に状態を更新できます正しい。 Reactはre-run最初のレンダリングを終了した直後に状態が更新されたコンポーネントを再実行しますそれは高価ではありません。
レンダリング中の更新は、正確には
getDerivedStateFromProps
は常に概念的なものでした。
本質的に、追加のコミットを取り除くことで無料でパフォーマンスを節約します。レンダリングが画面にコミットされた後にuseEffect
が実行されるためです。