0

I am using react-checkbox-tree and trying to get it to work using hooks. I am calling useState for nodes, checked, and expanded:

const [checked, setChecked] = useState<string[]>([]);
const [expanded, setExpanded] = useState<string[]>([]);
const [nodes, setNodes] = useState<Node[]>([]);

I pass the setChecked and setExpanded to the event handlers in checkbox tree:

        onExpand={(expanded) => {
                setExpanded(expanded);
                console.log(expanded);
            }
        }

        onCheck= {(checked) => {
            setChecked(checked);
            console.log(checked);
        }}

In my useEffect, I simulate a service call, and then call setNodes to set the nodes. This is working correctly - the checkbox tree is rendered. However, checking doesn't work. I added log statements and confirmed that checked array in onChecked is always empty. Expanding does seem to be working and it is correctly logging the expanded nodes, so not sure what I'm missing here.

Here is a simplified stripped down version of my code:

import React, { useState, useEffect } from 'react';
import 'react-checkbox-tree/lib/react-checkbox-tree.css';
import CheckboxTree, {Node} from 'react-checkbox-tree';

function CheckboxTreeTest() {

    const serviceResponseDummy = [{
        value: 'A',
        label: 'a',
        children: [
            { value: 'b', label: 'B', children: [] },
            { value: 'c', label: 'C', children: [{
                    value: 'd', label: 'D', children: []
                }]
            },
        ],
    }];

    const [checked, setChecked] = useState<string[]>([]);
    const [expanded, setExpanded] = useState<string[]>([]);
    const [nodes, setNodes] = useState<Node[]>([]);

    function dummyServiceCall():Promise<Node[]> {
        return new Promise<Node[]>((resolve, reject) => {
            setTimeout(() => {
                resolve(serviceResponseDummy);

            }, 1000);
        })
    }

    useEffect(() => {
        dummyServiceCall()
        .then((response: Node[]) => {
            setNodes(response);
        });
    });

    return (
        <CheckboxTree
            nodes={nodes}
            checked={checked}
            expanded={expanded}
            onExpand={(expanded) => {
                    setExpanded(expanded);
                    console.log(expanded);
                }
            }

            onCheck= {(checked) => {
                setChecked(checked);
                console.log(checked);
            }}
        />
    );
}

export default CheckboxTreeTest;
Jay Hu
  • 83
  • 7

1 Answers1

0

Your useEffect() is running all the time, resulting in constant re-renders of the checkbox tree because nodes is constantly getting replaced. You can see this by putting a console.logs in the .then() block (as I have below).

To get the useEffect() to just run once, use an empty dependency array:

 useEffect(() => {
    dummyServiceCall().then((response: Node[]) => {
      console.log(`setting ${JSON.stringify(response)}`);
      setNodes(response);
    });
  }, []);

I'm not familiar with react-checkbox-tree but when I ran your code in a codesandbox, it logged out sensible values for checked when I clicked on the first of the visible boxes (and correctly expanded and collapsed)

millhouse
  • 9,817
  • 4
  • 32
  • 40