function App() {
const [isDel, del] = useState(false);
const divRef = useRef(null);
console.warn('render divRef', divRef.current);
useEffect(() => {
console.warn('useEffect divRef', divRef.current);
}, []);
return (<div ref={divRef} onClick={() => del(true)}>
{isDel ? null : <Child />}
</div>);
}
function Child() {
return <p ref={(dom) => console.warn('dom is:', dom)}>Child</p>;
}
// 打印结果:
// render divRef null
// dom is null
// dom is <p/>
// useEffect divRef <div/>
render 阶段结束后,App 和 p 会被打上 Ref,commit 阶段时会根据 subtreeFlags 进行后序遍历 fiber 树,对带有 flags 的 fiber 进行 commitEffectsOnFiber,对 Ref 的节点执行 props.ref(stateNode)。
注意:stateNode 是在 completeWork 中创建 hostNode 并逐层添加到 hostParent.children 的。
function App() { const [isDel, del] = useState(false); const divRef = useRef(null); console.warn('render divRef', divRef.current); useEffect(() => { console.warn('useEffect divRef', divRef.current); }, []); return ( <div ref={dom => { console.warn('div dom is:', dom) }} onClick={() => del(true)}> {isDel ? null : <Child />} </div> );}function Child() { return <p ref={(dom) => console.warn('dom is:', dom)}>Child</p>;}
// 打印结果:
// render divRef null
// dom is null
// div dom is null
// dom is <p/>
// div dom is <div/>
// useEffect divRef null
unbindRef 是在 commit 阶段的 mutation 阶段执行的,bindRef 是在 commit 阶段的 layout 阶段执行的。