React中如何使用Ref获取节点及创建Ref数组处理Tree勾选?
Hey Javier, let's break down why you're only getting the last node in your onCheck callback and fix this properly!
What's Going Wrong Right Now
The core issue is simple: you're assigning all your TreeNode components to a single ref (this.myRef). Every time your loop function renders a new node, it overwrites the previous ref value. By the time the render finishes, this.myRef.current will only point to the last rendered node—no matter which node you check.
Step-by-Step Solution
We need to store a unique ref for each TreeNode instead of a single one. Here's how to implement this:
1. Initialize a Ref Collection
First, create an object in your component to hold references to every TreeNode. For class components, add this to your constructor:
constructor(props) { super(props); this.nodeRefs = {}; // Use each TreeNode's unique key as the object key }
2. Assign Refs to Each TreeNode
Instead of using a single ref, use a ref callback to store each node in your nodeRefs object. Update your loop function like this:
const loop = (data) => { return data.map((item) => { if (item.children && item.children.length) { return ( <TreeNode ref={(node) => (this.nodeRefs[item.key] = node)} // Store ref by item's unique key title={item.name} key={item.key} checked={item.checked} > {loop(item.children)} </TreeNode> ); } return ( <TreeNode ref={(node) => (this.nodeRefs[item.key] = node)} // Same approach for leaf nodes title={item.name} key={item.key} isLeaf={item.isLeaf} checked={item.checked} /> ); }); };
3. Fetch the Correct Node in onCheck
Now in your onCheck callback, use the event object to get the key of the node that was just checked/unchecked, then pull the corresponding ref from your nodeRefs object:
onCheck = (checkedKeys, event) => { // Get the unique key of the node that triggered the event const currentNodeKey = event.node.key; // Fetch the exact node ref from our collection const currentNode = this.nodeRefs[currentNodeKey]; if (!currentNode) return; console.log("Current checked node:", currentNode); // Now you can use DOM APIs to modify related nodes // Example: Update parent node's checked state const parentNode = currentNode.parentNode; if (parentNode) { const parentCheckbox = parentNode.querySelector(".ant-tree-checkbox-input"); if (parentCheckbox) { parentCheckbox.checked = event.checked; // Trigger a change event so React picks up the update parentCheckbox.dispatchEvent(new Event("change")); } } // Example: Update all child nodes' checked state const childNodes = currentNode.querySelectorAll(".ant-tree-node"); childNodes.forEach((child) => { const childCheckbox = child.querySelector(".ant-tree-checkbox-input"); if (childCheckbox) { childCheckbox.checked = event.checked; childCheckbox.dispatchEvent(new Event("change")); } }); };
A Quick Note About React Best Practices
While manually manipulating the DOM works for your use case, React's core philosophy is to drive UI changes through state. Whenever possible, it's better to update your treeData or checkedKeys state instead of touching the DOM directly. For example, you could write a recursive function to update the checked property of the current node, its parent, and children, then call setState to re-render the Tree. This avoids potential inconsistencies between your state and the actual DOM.
内容的提问来源于stack exchange,提问作者Javier

