skip to Main Content

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.

enter image description here

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


  1. 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 trigger useEffect, 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 storing selectedNodes in a parent component and then rendering data with checked 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 entire useEffect() 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 of onChange(). It could even be in this component. Make sure that objects in data that have been selected have the checked property.

    Login or Signup to reply.
  2. 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 current useEffect to setState which is rendering in an infinite loop.

    const treeData = React.useMemo(() => props.tree_unit_data, [props.tree_unit_data]);
    
    <DropdownTreeSelect
      data={treeData}
      onChange={onChange}
      texts={{ placeholder: 'Select Node' }}
    />
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search