useRef 打印结果

26 阅读1分钟
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 阶段执行的。