如何在React中访问孩子的状态?(反应钩)

mik*_*why 5 javascript reactjs react-hooks

什么是使用react-hook访问孩子的状态的最佳解决方案?

我尝试了各种方法。在我最终得出的结论下面。

表格(父母)


export const Form: FunctionComponent<IProps> = ({ onFinish, initState }) => {
  const formInputsStateRef = useRef({})

  const handleFinish = () => {
    const params = formInputsStateRef.current
    console.log(params)
    onFinish(params)
  }

  return (
    <div>
      <Inputs initState={initState} stateRef={formInputsStateRef}  />
      <S.Button onClick={handleFinish}>
        Finish
      </S.Button>
    </div>
  )
}

Run Code Online (Sandbox Code Playgroud)

输入(子项)

export const Inputs: FunctionComponent<IProps> = ({ initState, stateRef }) => {
  const [pool, setPool] = useState(initState.pool)
  const [solarPanel, setSolarPanel] = useState(initState.solarPanel)

  useEffect(() => {
    stateRef.current = { pool, solarPanel }
  })

  const handlePoolInput = () => {
    setPool('new pool')
  }

  const handleSolarPanelInput = () => {
    setSolarPanel('new solar panel')
  }

  return (
    <div>
      <h2>{pool}</h2>
      <S.Button onClick={handlePoolInput}>Change pool</S.Button>
      <h2>{solarPanel}</h2>
      <S.Button onClick={handleSolarPanelInput}>Change solar panel</S.Button>
      <h2>-----</h2>
    </div>
  )
}
Run Code Online (Sandbox Code Playgroud)

它以这种方式工作,但是我不喜欢它在每个渲染器上创建一个对象的事实。


输入项(子项)

useEffect(() => {
    stateRef.current = { pool, solarPanel }
})
Run Code Online (Sandbox Code Playgroud)

Shu*_*tri 4

您可以将 pool 和 SolarPanel 作为第二个参数传递给 ,useEffect以便仅在这些值发生变化时将状态更新为 ref

export const Inputs: FunctionComponent<IProps> = ({ initState, stateRef }) => {
  const [pool, setPool] = useState(initState.pool)
  const [solarPanel, setSolarPanel] = useState(initState.solarPanel)

  useEffect(() => {
    stateRef.current = { pool, solarPanel }
  }, [pool, solarPanel])

  const handlePoolInput = () => {
    setPool('new pool')
  }

  const handleSolarPanelInput = () => {
    setSolarPanel('new solar panel')
  }

  return (
    <div>
      <h2>{pool}</h2>
      <S.Button onClick={handlePoolInput}>Change pool</S.Button>
      <h2>{solarPanel}</h2>
      <S.Button onClick={handleSolarPanelInput}>Change solar panel</S.Button>
      <h2>-----</h2>
    </div>
  )
}
Run Code Online (Sandbox Code Playgroud)

然而,要使用 ref 对子值进行更受控制的处理,您可以使用useImperativeHandlehook。

孩子

const InputsChild: FunctionComponent<IProps> = ({ initState, ref }) => {
  const [pool, setPool] = useState(initState.pool)
  const [solarPanel, setSolarPanel] = useState(initState.solarPanel)

  useImperativeHandle(ref, () => ({
    pool,
    solarPanel
  }), [pool, solarPanel])

  const handlePoolInput = () => {
    setPool('new pool')
  }

  const handleSolarPanelInput = () => {
    setSolarPanel('new solar panel')
  }

  return (
    <div>
      <h2>{pool}</h2>
      <S.Button onClick={handlePoolInput}>Change pool</S.Button>
      <h2>{solarPanel}</h2>
      <S.Button onClick={handleSolarPanelInput}>Change solar panel</S.Button>
      <h2>-----</h2>
    </div>
  )
}

export const Inputs = forwardRef(InputsChild);
Run Code Online (Sandbox Code Playgroud)

家长

export const Form: FunctionComponent<IProps> = ({ onFinish, initState }) => {
  const formInputsStateRef = useRef({})

  const handleFinish = () => {
    const params = formInputsStateRef.current
    console.log(params)
    onFinish(params)
  }

  return (
    <div>
      <Inputs initState={initState} ref={formInputsStateRef}  />
      <S.Button onClick={handleFinish}>
        Finish
      </S.Button>
    </div>
  )
}
    
Run Code Online (Sandbox Code Playgroud)