【问题标题】:How to access child's state in React? (React Hooks)如何在 React 中访问孩子的状态? (反应钩子)
【发布时间】:2019-02-15 04:08:13
【问题描述】:

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

我尝试了各种方法。低于我最终得到的那个。

表单(父)


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>
  )
}

输入(子)

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>
  )
}

它是这样工作的,但我不喜欢它在每次渲染时都创建一个对象的事实。


输入(子)

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

【问题讨论】:

    标签: javascript reactjs react-hooks


    【解决方案1】:

    您可以将 pool 和 solarPanel 作为第二个参数传递给 useEffect,以便状态更新为仅在这些值更改时引用

    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>
      )
    }
    

    但是,如果要使用 ref 对子值进行更可控的处理,您可以使用 useImperativeHandle 钩子。

    儿童

    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);
    

    家长

    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>
      )
    }
        
    

    【讨论】:

    • 感谢第一个解决方案有效。第二个是useImperativeHandle 不幸的是没有。
    • 第二个解决方案导出输入组件export const Inputs = forwarRef(InputsChild);时是否使用forwardRef
    • 有效,需要小改动:const InputsChild: FunctionComponent&lt;IProps&gt; = ({ initState }, ref ) =&gt; {...} 第一种方法的优点是什么? more controlled handle of child values 是什么意思?
    • 通过使用 useImperativeHandle,您可以限制父级仅访问子级想要公开的那些方法/值。
    • @ecoe,InputsChild 是传递给 forwardRef hoc 的组件,因此父级将引用 Inputs 而不是 InputsChild
    猜你喜欢
    • 2015-03-08
    • 2020-04-29
    • 1970-01-01
    • 2020-10-23
    • 1970-01-01
    • 1970-01-01
    • 2020-08-12
    • 2020-05-23
    • 2021-10-12
    相关资源
    最近更新 更多