如何在 React 中访问 child 的状态? (反应钩子)
How to access child's state in React? (React Hooks)
使用 react-hooks 访问 child 状态的最佳解决方案是什么?
我尝试过各种方法。在我最后得到的那个下面。
表格 (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>
)
}
输入 (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>
)
}
它以这种方式工作,但我不喜欢它在每次渲染时创建一个 object 的事实。
输入(Child)
useEffect(() => {
stateRef.current = { pool, solarPanel }
})
您可以将 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>
)
}
然而,要使用 ref 更好地控制 child 值,您可以使用 useImperativeHandle
钩子。
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>
)
}
使用 react-hooks 访问 child 状态的最佳解决方案是什么?
我尝试过各种方法。在我最后得到的那个下面。
表格 (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>
)
}
输入 (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>
)
}
它以这种方式工作,但我不喜欢它在每次渲染时创建一个 object 的事实。
输入(Child)
useEffect(() => {
stateRef.current = { pool, solarPanel }
})
您可以将 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>
)
}
然而,要使用 ref 更好地控制 child 值,您可以使用 useImperativeHandle
钩子。
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>
)
}