简体   繁体   English

ref 回调是否总是按照它们在 render() 中声明的顺序被调用?

[英]Will ref callbacks always be invoked in the order they are declared in render()?

So far, I haven't been able to track down documentation or React source that answers this question.到目前为止,我还没有找到回答这个问题的文档或 React 源代码。 For the following React component ...对于以下 React 组件...

class MyComponent extends React.Component {
    divRefs = [];

    addRef = (node) => {
        if (node) {
            this.divRefs.push(node.id);
        }
    };

    render() {
        return (
            <>
                <div id="node1" ref={ this.addRef }>one</div>
                <div id="node2" ref={ this.addRef }>two</div>
                <div id="node3" ref={ this.addRef }>three</div>
            </>
        );
    }
}

... will the order of ids in the divRefs array consistently follow the order that the divs are included in the render declaration? ... divRefs数组中 id 的顺序divRefs始终遵循 div 包含在渲染声明中的顺序? (ie the ref callbacks are invoked in an identical order as render) The resulting array looks like this, but can I reliably expect this result, in this order? (即以与渲染相同的顺序调用 ref 回调)结果数组看起来像这样,但我可以可靠地期望这个结果,按这个顺序吗? Why or why not?为什么或者为什么不?

...
console.log(this.divRefs); // ['node1', 'node2', 'node3']
...

You get following guarantee for callback refs:您将获得回调引用的以下保证:

React will call the ref callback with the DOM element when the component mounts , and call it with null when it unmounts. React 将在组件挂载时使用 DOM 元素调用 ref 回调,并在卸载时使用 null 调用它。 Refs are guaranteed to be up-to-date before componentDidMount or componentDidUpdate fires. Refs 保证在 componentDidMount 或 componentDidUpdate 触发之前是最新的。

Now the question is, in which order are the children mounted:现在的问题是,孩子们的安装顺序是:

it is up to React to decide in which order to actually call their render functions由 React 决定实际调用其渲染函数的顺序

So, there seems to be no 100% guarantee, that children are consistently rendered, mounted and ref callbacks invoked corresponding to their order in render code.因此,似乎没有 100% 的保证,子项始终按照render代码中的顺序进行render 、挂载和调用 ref 回调。 To be safe, you can instead update divRefs directly via indices, which are passed to addRef :为了安全起见,可以改为更新divRefs直接通过指数来传递到addRef

 class MyComponent extends React.Component { divRefs = []; addRef = (node, index) => { if (node) { this.divRefs[index] = node.id console.log(`Set node ${node.id}`, JSON.stringify(this.divRefs)) } }; render() { return ( <React.Fragment> <div id="node1" ref={ n => this.addRef(n, 0) }>one</div> <div id="node2" ref={ n => this.addRef(n, 1) }>two</div> <div id="node3" ref={ n => this.addRef(n, 2) }>three</div> </React.Fragment> ); } } ReactDOM.render(<MyComponent />, document.getElementById("root"));
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.10.1/umd/react.production.min.js" integrity="sha256-vMEjoeSlzpWvres5mDlxmSKxx6jAmDNY4zCt712YCI0=" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.10.1/umd/react-dom.production.min.js" integrity="sha256-QQt6MpTdAD0DiPLhqhzVyPs1flIdstR4/R7x4GqCvZ4=" crossorigin="anonymous"></script> <div id="root"></div>

This also avoids stale entries caused by push , when a ref is dropped and then re-added to a DOM node.这也避免了push导致的陈旧条目,当 ref 被删除然后重新添加到 DOM 节点时。 Alternatively, create an array of nodes and map over them to get rid of manual indices:或者,创建一个节点数组并映射它们以摆脱手动索引:

// render()
const nodes = [{ id: "node1", label: "one" }, { id: "node2", label: "two" }];
return nodes.map((n, idx) => (
    <div id={n.id} key={n.id} ref={n => this.addRef(n, idx)}> {n.label} </div>
));

Hope, it helps!希望能帮助到你!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM