首页 > 解决方案 > 反应子组件不会在更新的父状态上重新渲染

问题描述

我试图找到解决方案,但似乎没有任何效果。我想要做的是创建一个带有复选框的 TreeView 。当您在复选框中选择一个项目时,它会附加一个列表,当您取消选中它时,将其从列表中删除。这一切都有效,但是当我折叠和展开 TreeItem 时遇到的问题是,我失去了选中状态。我尝试通过检查我选择的列表来解决这个问题,但是每当运行 useEffect 函数时,子组件都没有正确的父状态列表。

我有以下父组件。这是与此类似的形式(https://www.youtube.com/watch?v=HuJDKp-9HHc

export const Parent = () => {
 const [data,setData] = useState({
   name: "",
   dataList : [], 
   // some other states
  })

 const handleListChange = (newObj) => {
   //newObj : { field1 :"somestring",field2:"someotherString" }
   setDataList(data => ({ 
     ...data,
      dataList: data.actionData.concat(newObj)
   }));

   return (
     {steps.current === 0 && <FirstPage //setting props} 
      ....

     {step.current == 3 && <TreeForm dataList={data.dataList} updateList={handleListChange}/> 
   )

 }


Tree 组件是一个 Material UI TreeView,但自定义为包含一个复选框 在此处输入图像描述

由于来回传递的数据的大小,每个节点都是从 API 调用动态加载的。(根被加载,然后根据您选择的节点,当时加载子节点)。

我的树类是

export default function Tree(props) {
 
useEffect(() => {

// call backend server to get roots 
setRoots(resp) 

})

return ( 
<TreeView >
Object.keys(root).map(key => ( 
<CustomTreeNode key={root.key} dataList={props.dataList} updateList={props.updateList}

)))}

</TreeView>

)

CustomTreeNode 定义为

export const CustomTreeNode = (props) => {

const [checked,setChecked] = useState(false)
const [childNodes,setChildNodes] = useState([])

async function handleExpand() {

  //get children of current node from backend server 
  childList = []
  for( var item in resp) {

     childList.push(<CustomTreeNode dataList={props.dataList} updateList={props.updateList} />)
   } 

  setChildNodes(childList) 
}

const handleCheckboxClick () => {
  if(!checked){
   props.updateList(obj)
   }
else{
   //remove from list 
}

  setChecked(!checked)

}

// THIS IS THE ISSUE, props.dataList is NOT the updated list. This will work fine
// if I go to the next page/previous page and return here, because then it has the correct dataList. 
useEffect(() => {

        console.log("Tree Node Updating")
        var isInList = props.dataList.find(function (el) {
            return el.field === label
        }) !== undefined;

        if (isInList) {
            setChecked(true);
        } else {
            setChecked(false)
        }
    }, [props.dataList])

return ( <TreeItem > {label} </TreeItem> )

}

标签: javascriptreactjsstate

解决方案


您将 props.data 放在 useEffect 依赖数组中而不是 props.dataList 中,因此当 props.dataList 更改时它不会更新。

编辑:您的选中状态是 CustomTreeNode 类的状态变量。当一棵树被销毁时,该状态变量也被销毁。您需要将检查状态存储在未被破坏的更高组件中,可能作为检查布尔值列表。


推荐阅读