前言
本篇文章屬於 React通訊 > 父子通訊 > 父元件呼叫子元件 的內容。
父元件呼叫子元件的場景:
- 子元件被多個地方使用,需要單獨封裝
- 子元件邏輯較重,使用完全受控模式成本較高
使用父元件呼叫子元件進行邏輯呼叫有以下優勢:
- 子元件可以封裝,進行復用。並且裡面的邏輯不受外界干擾
- 可以把更多相關邏輯封裝在子元件裡,而不需要傳遞 props
- 蒐集資料簡單
正文
Class Component
Hooks
使用到的hooks:useImperativeHandle
和 useRef
/* child子元件 */
// https://reactjs.org/docs/hooks-reference.html#useimperativehandle
import {useState, useImperativeHandle} from 'react';
...
// props子元件中需要接受ref
const ChildComp = ({cRef}) => {
const [val, setVal] = useState();
// 此處注意useImperativeHandle方法的的第一個引數是目標元素的ref引用
useImperativeHandle(cRef, () => ({
// changeVal 就是暴露給父元件的方法
changeVal: (newVal) => {
setVal(newVal);
}
}));
...
return (
<div>{val}</div>
)
}
/* FComp 父元件 */
import {useRef} from 'react;
...
const FComp = () => {
const childRef = useRef();
const updateChildState = () => {
// changeVal就是子元件暴露給父元件的方法
childRef.current.changeVal(99);
}
...
return (
<>
{/* 此處注意需要將childRef通過props屬性從父元件中傳給自己 cRef={childRef} */}
<ChildComp cRef={childRef} />
<button onClick={updateChildState}>觸發子元件方法</button>
</>
)
}
方法二、參考react官方文件:
import {useState, useImperativeHandle,forwardRef} from 'react';
// props子元件中需要接受ref
let ChildComp = (props,ref) => {
// 此處注意useImperativeHandle方法的的第一個引數是目標元素的ref引用
useImperativeHandle(ref, () => ({
// changeVal 就是暴露給父元件的方法
changeVal: (newVal) => {
}
}));
return (
<div>{val}</div>
)
}
ChildComp = forwardRef(ChildComp)
/* FComp 父元件 */
import {useRef} from 'react';
const FComp = () => {
const childRef = useRef();
const updateChildState = () => {
// changeVal就是子元件暴露給父元件的方法
childRef.current.changeVal(99);
}
return (
<>
<ChildComp ref={childRef} />
<button onClick={updateChildState}>觸發子元件方法</button>
</>
)
}
總結
demo:
- props ref: https://codepen.io/specialCod...
- forwardRef: https://codepen.io/specialCod...
- common object: https://codepen.io/specialCod...
總結: - 都可以實現父元件呼叫子元件方法
- 無論是 props ref 還是 forwardRef 都是為了向子元件傳遞 ref
- 實現需要一個
ref
物件 (為什麼是ref
? 特性是?) 【其實只要是傳遞一個物件就可以,ref 應該是和元件生命週期有關係】 - Cannot read property 'getList' of undefined ( null in ref)
- 實現需要
useImperativeHandle
起到繫結方法到物件上的作用 - 給ref.current賦值是個副作用,所以一般在Did函式或者事件處理函式裡給ref.current賦值;
- 元件在解除安裝時要清理ref.current的值。
本質上useImperativeHandle就是在幫我們做這些事情。
todo:
- 受控通訊方式簡單介紹