I have a parent functional component <EditCard/>
that is a modal opened when the edit table row button is selected. This edit card contains a state variable called data
which consists of the data from the table row being edited. I am setting/modifying state on <EditCard/>
with the useState
hook.
<EditCard/>
has a child component <CategoryDropdown/>
which is a dropdown that accepts a prop data.assignCategory
as its selected value and a callback handleChange()
which updates the state value data
with the value selected from the dropdown.
When I select a new value from the dropdown handleChange()
is called and setData()
is called and I see the state being updated but <CategoryDropdown/>
is not re-rendered with the new selected value.
EditCard Component Code
export default function EditCard(props) {
const [data, setData] = useState(props.data);
const handleChange = () => event => {
let d = data;
d.assignCategory = event.target.value;
setData(d);
};
let assignCategoryCol = data.assignCategory !== undefined ? <AssignCategoryCol data={data} handleChange={handleChange}/> : <></>;
return (
<div>
{assignCategoryCol}
<Button>Update</Button>
</div>
)
}
{props.data.bucketTotal}`} <Lock/></Typography>)
};
const AssignCategoryCol = (props) => {
return (
<CategoryDropdown id={props.data.id} assignedCategory={props.data.assignCategory} handleDropdownChange={props.handleChange}/>)
};
const useStyles = makeStyles(theme => ({}));
CategoryDropdown Component
class CategoryDropdown extends Component {
constructor(props) {
super(props);
//TODO Get Categories from DB and set default
this.state = {
categories: ['Select One', 'Category1', 'Category2', 'Category3'],
};
}
render() {
return (
<div id={'categoryDropdown'}>
<Select onChange={this.props.handleDropdownChange(this.props.id)} value={this.props.assignedCategory}>
{this.state.categories.map((category) => {
return <MenuItem value={category}>{category}</MenuItem>
})}
</Select>
</div>
)
}
}
const styles = theme => ({});
export default withStyles(styles)(CategoryDropdown)
In order for React to know that something has changed in the state, you need to replace the current object with an entirely new object. Currently, react sees that it is the same object, so does nothing. It does not search the object to see if any properties have changed in it.
In your handleChange event handler, you have:
let d = data;
This is not copying the data object. Instead, now the variable "d" is pointing to the same object (in memory) that the variable "data" points to.
(For more info, read about "pass by reference" vs "pass by value").
To fix that, see the destructuring/ copying below:
const [data, setData] = useState(props.data)
const handleChange = event => {
let newData = {...data} //copy the object
newData.assignCategory = event.target.value;
setData(newData);
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With