web-dev-qa-db-ja.com

useEffectフック内で状態を設定できますか

他の状態に依存する状態があるとしましょう(たとえば、Aが変更されたときにBを変更したい場合)。

UseEffectフック内でAを監視し、Bを設定するフックを作成することは適切ですか?

ボタンをクリックすると、最初のエフェクトが起動し、bが変化し、次のレンダリングの前に2番目のエフェクトが起動するように、エフェクトはカスケードされますか?このようなコードを構造化することでパフォーマンスの低下はありますか?

let MyComponent = props => {
  let [a, setA] = useState(1)
  let [b, setB] = useState(2)
  useEffect(
    () => {
      if (/*some stuff is true*/) {
        setB(3)
      }
    },
    [a],
  )
  useEffect(
    () => {
      // do some stuff
    },
    [b],
  )

  return (
    <button
      onClick={() => {
        setA(5)
      }}
    >
      click me
    </button>
  )
}
24
Dan Ruswick

エフェクトは、1つのエフェクト内でsetStateを設定した場合でも、レンダリングフェーズの完了後に常に実行されます。別のエフェクトは、更新された状態を読み取り、レンダリングフェーズの後でのみアクションを実行します。

bchanging a以外の理由で変更される可能性がある場合を除き、同じ効果で両方のアクションを実行することをお勧めしますが、その場合も同じロジックを実行したい

4
Shubham Khatri

setState内でuseEffectを使用すると、おそらく発生させたくない無限ループが作成されます。

useEffectは各レンダリングの後に呼び出され、setStateがその内部で使用されると、コンポーネントは再レンダリングされ、useEffectなどを呼び出します。

useState内でuseEffectを使用しても無限ループが発生しない唯一のケースは、useEffect(() => {....}, [])のようなuseEffectの2番目の引数として空の配列を渡す場合です。エフェクト関数は、最初のマウント/レンダリングの後でのみ一度呼び出す必要があります。

18
Hossam Mourad

useEffectは、特定の小道具または状態をフックできます。そのため、無限ループフックを回避するために必要なことは、何らかの変数または状態をバインドすることです

例えば。

useEffect(myeffect, [])

上記の効果は、コンポーネントがレンダリングされた後にのみ発生します。これはcomponentDidMountライフサイクルに似ています

const [something, setSomething] = withState(0)
const [myState, setMyState] = withState(0)
useEffect(() => {
  setSomething(0)
}, myState)

上記の効果は、私の状態が変更された場合にのみ発動します。これは、すべての変化する状態が発動するわけではないことを除き、componentDidUpdateと同様です。

これでさらに詳細を読むことができます link

1
Dogies007