web-dev-qa-db-ja.com

Reactフックを使用してプロップを状態に同期する方法:setState()

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;

問題は、コンポーネントのロード時に状態が設定されていることです。しかし、新しい小道具を受け取ったとき、状態は更新されていません。この場合、状態を更新するにはどうすればよいですか?前もって感謝します。

44
METALHEAD

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;
67
Shubham Khatri

そのためには、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;

デモ

6
Dhaval Patel

この一般的な考えはフックに入れることができます:

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 (...);
}
5
bsapaka
1
gongeek
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を更新する前に状態を確認してから、値が更新され、継続的に再レン​​ダリングされないようにする必要があります。

1
Kajol Chaudhary

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が実行されるためです。

0
ford04