javascript - How to access child's state in React? (React Hooks) - Stack Overflow

What's the best solution to get access to the child's state using react-hooks?I've tried

What's the best solution to get access to the child's state using react-hooks?

I've tried various approaches. Below the one that I've ended up with.

Form (Parent)


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

Inputs (Child)

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

It works that way but I don't like the fact that it creates an object on every render.


Inputs(Child)

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

What's the best solution to get access to the child's state using react-hooks?

I've tried various approaches. Below the one that I've ended up with.

Form (Parent)


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

Inputs (Child)

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

It works that way but I don't like the fact that it creates an object on every render.


Inputs(Child)

useEffect(() => {
    stateRef.current = { pool, solarPanel }
})
Share Improve this question edited Feb 15, 2019 at 4:42 asked Feb 15, 2019 at 4:08 user2208706user2208706
Add a ment  | 

1 Answer 1

Reset to default 4

You could pass pool and solarPanel as the second argument to useEffect so that the state is updated to ref only on these values change

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

However to have a more controlled handle of child values using ref, you can make use of useImperativeHandle hook.

Child

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

Parent

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

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744283458a4566686.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信