Not able to set the state of the parent component on selecting the items in dropdown
Geetha198119071999 opened this issue · 4 comments
Describe the bug
Unable to set the state variable for this when used as sub component.
To Reproduce
adding the selectedNodes to a the function of props, but all the options are unchecked
Expected behavior
I wanted to capture the selectedNodes and attach them to the state variable of calling Component.(Parent)
I have the same issue, at first I thought it's because I'm doing something strange in my app, but it turns out this is easily reproducable, see here:
https://codesandbox.io/s/react-dropdown-tree-select-issue-reproduction-forked-mvss4q?file=/index.js
Since this doesn't work I'm curious how other people use this component, since it seems impossible to propagate the selection results to other components? 🤔
I have tried several different combinations of react versions and dropdown-tree-select component versions, but have not found any where this works.
Looking forward to finding out if I'm doing something really obviously wrong or if that's actually a flaw with the component 🤷
--- EDIT:
ok i just found this page https://github.com/dowjones/react-dropdown-tree-select/blob/main/docs/HOC.md
sadly all the codeSandbox links inside it are broken.
So if I get this right, the component expects never to be re-rendered while in use.
This might be some performance best-practice (haven't been using react long enough to judge that), but from all the react code I've seen so far I would say that this is extremely confusing and would deserve a big highlight/mention high up in the readme (none of the code samples mention anything in that direction and there is no mention of "state propagation" or "interacting with other components" or anything like that in the readme).
sadly all the codeSandbox links inside it are broken.
I just checked and they all work for me. Are you sure it wasn't a glitch or a browser issue on your end?
So if I get this right, the component expects never to be re-rendered while in use.
Not true. You can re-render this but then there are ripple effects in certain use cases that may be undesirable. This is why the HoC example exists to tailor it to your needs. React re-render and preventing it are basic tenets of how React works.
I had the same issue when trying to use the DropdownTreeSelect
component inside a form using Formik, at any form change the DropdownTreeSelect
would reset. It's strange that the component was created and no one thought it would be used inside forms with state changes and that somehow the onChange
prop should have a value argument in order to receive the current value of the DropdownTreeSelect, and DropdownTreeSelect
component should have a value prop as well.
The solution that I found were to manually change the data in order to pass the checked items and keep the DropdownTreeSelect changes when the parent node component state changes.
`import { get, set } from 'lodash';
import React, { useState } from 'react';
import DropdownTreeSelect from 'react-dropdown-tree-select';
function getPath(node) {
return node._id
.replace('YOUR-DROPDOWN-ID-', '')
.split('-')
.map((number) => [${number}]
)
.join('.children');
}
const Content = () => {
const [initialData, setInitialData] = useState(YOUR_INITIAL_DATA)
const [data, setData] = useState(null);
const handleDataChange = ({ selectedNodes, setFieldValue, currentNode }) => {
const newData = [...initialData];
const currentNodeParentPath = currentNode._parent && getPath({ _id: currentNode._parent });
if (currentNodeParentPath) {
// if children node is selected keep parent expanded
set(newData, currentNodeParentPath, {
...get(newData, currentNodeParentPath),
expanded: true,
});
}
selectedNodes.forEach((node) => {
const path = getPath(node);
set(newData, path, {
...get(newData, path),
checked: true,
});
});
// if there's no node selected set to null, so the data prop will receive the initialData
setData(selectedNodes.length ? newData : null);
}
return <DropdownTreeSelect
id="YOUR-DROPDOWN-ID"
texts={{
placeholder: 'Search',
}}
data={data || initialData}
onChange={(currentNode, selectedNodes) => {
handleDataChange({
selectedNodes,
setFieldValue,
currentNode,
});
}}
/>
}
`
To keep the expansion in deeper leaf nodes the following code
if (currentNodeParentPath) { // if children node is selected keep parent expanded set(newData, currentNodeParentPath, { ...get(newData, currentNodeParentPath), expanded: true, }); }
should be called for all parent nodes until it reaches the root.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 10 days if no further activity occurs. Thank you for your contributions.