【问题标题】:React child component not re-rendering on updated parent state反应子组件不会在更新的父状态上重新渲染
【发布时间】:2021-09-21 18:28:28
【问题描述】:

我已尝试找到解决此问题的方法,但似乎没有任何效果。我想要做的是创建一个带有复选框的 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> )

}

【问题讨论】:

    标签: javascript reactjs state


    【解决方案1】:

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

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

    【讨论】:

    • 抱歉,这是我的问题的一种类型,但在我的实际代码中是正确的。我已对其进行了更新以反映这一点。
    • 您在这里有很多错别字,我不确定这是您的代码的一部分还是您的错误。使用 setDataList 而不是 setData。在您的 Tree 类中,您将 props.data 作为道具发送,而不是 props.dataList,后者是从其他组件发送的。
    • @qBoss 我想我可能发现了你的错误。检查编辑
    • 抱歉错别字,我没有发布我的实际代码来取出可识别信息,只是写了相关部分。如果您看一下我在 CustomTreeNode 中的 useEffect 函数,这基本上就是我正在做的事情,但我遇到的问题是 props.dataList 不是父组件中 dataList 的最新状态。 @奥斯卡
    猜你喜欢
    • 1970-01-01
    • 2016-02-23
    • 1970-01-01
    • 1970-01-01
    • 2021-06-20
    • 1970-01-01
    • 2021-01-27
    • 2021-04-06
    • 2015-11-03
    相关资源
    最近更新 更多