I'm having all kinds of trouble recovering values from a ReactDropdownTreeSelect. The component seems to keep it's state just fine, up until I want save the results of a change. However I try to do this, the component loses it's state and nothing is selected. What am i missing?
This is a simplest example, nearly identical to the one in the help, that shows the problem. One line breaks it...
import React, { useState, useEffect } from "react"
import DropdownTreeSelect from "react-dropdown-tree-select"
function DebugSelector() {
const [mySelected, setMySelected] = useState([]);
const [lastChanged, setLastChanged] = useState({});
const tarifs = {
label: "all tarifs", value: "all", children: [
{ label: "second level tarif", value: "secondLevel" },
{ label: "another 2nd level", value: "secondLevel2" }
]
}
const onChange = function (currNode, selectedNodes) {
debugger
// Any of these lines will break it. The component loses its state.
//setMySelected(selectedNodes);
//setMySelected([...selectedNodes]);
//setLastChanged(currNode);
setLastChanged(JSON.parse(JSON.stringify(currNode)))
}
return (
<DropdownTreeSelect data={tarifs} onChange={onChange}></DropdownTreeSelect>
)
}
export default DebugSelector;
To preserve its state, react-dropdown-tree-select
needs to be wrapped in a class component that prevents re-renders if props have not changed. The class component can then proxy the onChange handler. This is my working wrapper...
import React, { Component } from "react"
import DropdownTreeSelect from "react-dropdown-tree-select"
import isEqual from "lodash/isEqual"
import { TarifForTreeSelect } from "interfaces/TarifForTreeSelect"
interface IProps {
data: TarifForTreeSelect
onChange: (currentNode: any, selectedNodes: any) => void
hasError?: any
contentTitle?: string
triggerTitle?: string
isLoading?: boolean
}
interface IState {
data: TarifForTreeSelect
}
class TarifsSelector extends Component<IProps, IState> {
constructor(props: IProps) {
super(props)
this.state = { data: props.data }
}
componentWillReceiveProps = (nextProps: IProps) => {
if (!isEqual(nextProps.data, this.state.data)) {
this.setState({ data: nextProps.data })
}
}
shouldComponentUpdate = (nextProps: IProps) => {
return !isEqual(nextProps.data, this.state.data)
}
render() {
const onChangeTemp = (currentNode: any, selectedNodes: any) => {
this.props.onChange(currentNode, selectedNodes)
}
return (
<>
<DropdownTreeSelect data={this.state.data && this.state.data.value !== "" ? this.state.data : []} onChange={onChangeTemp} showDropdown="always" />
</>
)
}
}
export default React.memo(TarifsSelector)