function App()
{
const [rows_data, SET_rows_data] = useState([]);
useEffect(() => {
get_rows_data(SET_rows_data); //Fetches the data. Runs only once
}, []);
useEffect(() => {
console.log(rows_data); //This rightly trigggers twice, and shows an empty array and the full array once fetched
}, [rows_data]);
return (
<div>
{Table_Renderer(rows_data)}
</div>
); //Doesn't re-render when rows_data changes
}
function get_rows_data(SET_rows_data)
{
fetch(...)
.then((res) => res.json())
.then((data) => {
SET_rows_data(data["rows"]); //Required data is within the "rows" object
});
}
function Table_Renderer(rows_data)
{
return (
<table>
<thead>
...
</thead>
<tbody >
{rows_data.map(row => {
return (
<tr>
...
</tr>
)
})}
</tbody>
</table>
)
}
export default (App);
I've added comments above to explain the issue.
The console.log in the useEffect, triggers twice as expected. But the 2nd render doesn't happen, even though the data in the JSX has changed.
If I re-save my work while 'npm start' is running, the data is properly displayed though
CodePudding user response:
Hi @Dalhousie,
As you describe above, The Table_Renderer
component is not re-rendering when the rows_data
state changes. Its obvious behavior
Because Table_Renderer
component does not have access to the rows_data
state, and so it is not aware that the state has changed.
function App() {
const [rows_data, SET_rows_data] = useState([]);
useEffect(() => {
get_rows_data(SET_rows_data); // Fetches the data. Runs only once
}, []);
return (
<div>
<Table_Renderer rowsData={rows_data} />
</div>
);
}
function Table_Renderer({ rowsData }) {
return (
<table>
<thead>
...
</thead>
<tbody>
{rowsData.map(row => {
return (
<tr>
...
</tr>
);
})}
</tbody>
</table>
);
}