反应子组件不会在更新的父状态上重新渲染

时间:2021-07-12 15:20:09

标签: javascript reactjs state

我试图找到解决方案,但似乎没有任何效果。我想要做的是创建一个带有复选框的 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,但自定义为包含一个复选框 enter image description here

由于来回传递的数据的大小,每个节点都是从 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> )

}

1 个答案:

答案 0 :(得分:1)

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

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