I am attempting to implement a tree dropdown in a React application using the ‘react-dropdown-tree-select’ package, and it worked without issue until we attempted to change the state.
import React, { useState, useEffect } from 'react';
import DropdownTreeSelect from 'react-dropdown-tree-select';
import 'react-dropdown-tree-select/dist/styles.css';
function TreeDropDown(props) {
const { tree_unit_data, handleTreeUnitListChange } = props;
const [treeData, setTreeData] = useState(tree_unit_data);
useEffect(() => {
// Update the treeData when tree_unit_data prop changes
setTreeData(tree_unit_data);
}, [tree_unit_data]);
const onChange = (currentNode, selectedNodes) => {
// Handle the onChange event here
handleTreeUnitListChange(selectedNodes) //This will break the DropdownTreeSelect and if we comment this it work
};
return (
<DropdownTreeSelect
data={treeData}
onChange={onChange}
texts={{ placeholder: 'Select Node' }}
/>
);
}
export default TreeDropDown;
I even attempted to set the state in this component, and it also yielded the same result
const onChange = (currentNode, selectedNodes) => {
// Handle the onChange event here
setTreeUnits(selectedNodes)
};
Somehow, it gets re-rendered whenever the state changes. I am somewhat blocked by this issue, and I would greatly appreciate it if someone could assist in identifying and resolving the problem.
Getting above exception as well when clicking on the dropdown
For testing purpose this data can be used
const treeData = [
{
label: 'Node 1',
children: [
{
label: 'Node 1.1',
},
{
label: 'Node 1.2',
children: [
{
label: 'Node 1.2.1',
},
{
label: 'Node 1.2.2',
},
],
},
],
},
{
label: 'Node 2',
children: [
{
label: 'Node 2.1',
},
{
label: 'Node 2.2',
},
],
},
];
React Version : 18.2
Node Version: 18.15.0
NPM Version: 9.5.0
2
Answers
Don’t set state inside a
useEffect
hook. It can cause infinite loops since setting state will cause a re-render, which will in turn triggeruseEffect
, and so on.It’s difficult to answer your question without knowing exactly what
handleTreeUnitListChange()
does. I will make the huge assumption that it’s storingselectedNodes
in a parent component and then renderingdata
withchecked
properties depending on whether the user just selected or unselected that node.If that’s indeed the case, you don’t need to use state in this component at all! Delete the line where you call
useState()
and your entireuseEffect()
callback.If that’s not the case, you should store the
data
state in somewhere it makes sense to do that and modify it based on the return value ofonChange()
. It could even be in this component. Make sure that objects indata
that have been selected have thechecked
property.In your case, I don’t feel a state is even required. You can directly pass
treeData
as follows. And write this line in your component. And remove currentuseEffect
to setState which is rendering in an infinite loop.