Reputation: 83
hi i'm really new in react, so i have a table which contains a bunch of data, i would like to assign the value of selected row to my setState but the output doesnt seems like what i expected to be, i made a simpler version of the code so here it is.
App.js :
import React from "react";
import DataTable from "react-data-table-component";
const app = () => {
const [selectedData, setSelectedData] = React.useState();
const data = [
{ name: "Jade", age: "25" },
{ name: "Brian", age: "15" }
];
const columns = [
{
name: "Name",
selector: "name"
},
{
name: "Age",
selector: "age"
}
];
const handleChange = (state) => {
setSelectedData(state.selectedRows);
console.log(selectedData);
};
return (
<div>
<DataTable
data={data}
columns={columns}
selectableRows
onSelectedRowsChange={handleChange}
/>
</div>
);
};
export default app;
Upvotes: 2
Views: 16190
Reputation: 83
solved this issue by moving the data variable to global scope, this happen because the data variables keeps re-rendering inside the component
import DataTable from "react-data-table-component";
const data = [
{ name: "Jade", age: "25" },
{ name: "Brian", age: "15" }
];
const app = () => {
const [selectedData, setSelectedData] = React.useState();
const columns = [
{
name: "Name",
selector: "name"
},
{
name: "Age",
selector: "age"
}
];
const handleChange = (state) => {
setSelectedData(state.selectedRows);
console.log(selectedData);
};
return (
<div>
<DataTable
data={data}
columns={columns}
selectableRows
onSelectedRowsChange={handleChange}
/>
</div>
);
};
export default app;```
Upvotes: 4
Reputation: 194
So your code is complete. There is no problem with it. This is just how React functions. Any state changes in React are batched. So after you have set the state, your setState method does not immediately update the state in the state variable. Instead it waits for the synchronous scope around the setState to complete. Only after that your state variable has the updated value.
return (
<div>
<DataTable
data={data}
columns={columns}
selectableRows
onSelectedRowsChange={handleChange}
/>
<div>{selectedData[0] ? selectedData[0].name : ''}</div>
</div>
If you add the line I have added here, you will see that your selectedData does get updated with the selected value.But if you will try to access the selectedData in the synchronous scope of where you are setting the selectedData by calling setSelectedData, you will never see the currently selected data. Also, if you would like to experiment further with this, try changing your selection again and again, you will see that the line console.log(selectedData); will display the previously selected value. This is a property of react to batch all state updates made in a synchronous scope altogether and make all the state changes once the control has reached the end of the scope.
Also if you do want to show your selected data, better use event.selectedRows for the same instead of selectedData.
Elaborate example of how setstate works :
const [someState, setSomeState] = useState(0);
//Assume we call this function on some event
const eventHandler = () => {
//line 1 setSomeState(someState + 1);
//line 2 setSomeState(someState + 1);
//line 3 setSomeState(someState + 1);
}
Now what will be the value of someState after line 3. It will be 1. Why? The first line takes the value of someState which is '0' and adds 1 to it, tries to set the new state with value as 1. But when we go to line 2, where we are again trying to access someState and we expect someState to be updated by line1, that is not going to happen. The value of someState will still be 0.Why? Because react waits for the entire block to first finish and only after that it really updates the state. This is an optimization technique that React has within itself. Also, if you want to see the previously set state, there is one workaround for that too.
const eventHandler = () => {
setSomeState(someState + 1);
setSomeState((prevState) => {
return prevState + 1;
});
setSomeState((prevState) => {
return prevState + 1;
});
}
Now this will update your state on each line.
Upvotes: 1