I have two files/components:
Createrisk.jsx
for creating individual risksTablepage.jsx
displays the risks in an MUI Data Grid
The problem is Tablepage renders only the attributes from Createrisk which are not dependent on user input i.e the ID and a Test attribute. I believe this makes sense, on first render attributes tied to inputs are empty.
How do I get the Tablepage component to re-render? Ideally tied to this event on Createrisk:
<button onClick={handleSubmission}>Store my data</button>
I have a vague idea I need a useState, but I am unsure how to do this across different components (JSX files).
Createrisk.jsx
:
function Createrisk() {
function handleSubmission() {
var risks = JSON.parse(localStorage.getItem("allrisks"));
if (risks == null) {
risks = [];
}
let riskitem = {
riskname: document.getElementById("rname").value,
riskdesc: document.getElementById("rdesc").value,
riskimpact: document.getElementById("rimpact").value,
test: "test",
};
risks.push(riskitem);
let i = 1;
risks.map((n) => {
n["id"] = i;
i++;
});
localStorage.setItem("allrisks", JSON.stringify(risks));
}
return (
<div>
<input type="text" id="rname" placeholder="Risk Name" />
<input type="text" id="rdesc" placeholder="Risk Description" />
<input type="text" id="rimpact" placeholder="Risk Impact" />
<button onClick={handleSubmission}>Store my data</button>
</div>
);
}
export default Createrisk;
Tablepage.jsx
:
function Tablepage() {
const risksfromstorage = JSON.parse(localStorage.getItem("allrisks"));
const columns = [
{ field: "id", headerName: "ID", width: 350 },
{ field: "rname", headerName: "Risk Name", width: 350 },
{ field: "rdesc", headerName: "Risk Desc", width: 350 },
{ field: "rimpact", headerName: "Risk Impact", width: 350 },
{ field: "test", headerName: "test", width: 350 },
];
const rows = risksfromstorage.map((row) => ({
id: row.id,
rname: row.rname,
rdesc: row.rdesc,
rimpact: row.rimpact,
test: row.test,
}));
return (
<div>
<DataGrid getRowId={(row) => row.id} columns={columns} rows={rows} />
</div>
);
}
export default Tablepage;
As one can see, the Array/Object gets added to localstorage. Only the non-input attributes are populated in the table (ID & Test)
Img showing Table and LocalStorage
I have two files/components:
Createrisk.jsx
for creating individual risksTablepage.jsx
displays the risks in an MUI Data Grid
The problem is Tablepage renders only the attributes from Createrisk which are not dependent on user input i.e the ID and a Test attribute. I believe this makes sense, on first render attributes tied to inputs are empty.
How do I get the Tablepage component to re-render? Ideally tied to this event on Createrisk:
<button onClick={handleSubmission}>Store my data</button>
I have a vague idea I need a useState, but I am unsure how to do this across different components (JSX files).
Createrisk.jsx
:
function Createrisk() {
function handleSubmission() {
var risks = JSON.parse(localStorage.getItem("allrisks"));
if (risks == null) {
risks = [];
}
let riskitem = {
riskname: document.getElementById("rname").value,
riskdesc: document.getElementById("rdesc").value,
riskimpact: document.getElementById("rimpact").value,
test: "test",
};
risks.push(riskitem);
let i = 1;
risks.map((n) => {
n["id"] = i;
i++;
});
localStorage.setItem("allrisks", JSON.stringify(risks));
}
return (
<div>
<input type="text" id="rname" placeholder="Risk Name" />
<input type="text" id="rdesc" placeholder="Risk Description" />
<input type="text" id="rimpact" placeholder="Risk Impact" />
<button onClick={handleSubmission}>Store my data</button>
</div>
);
}
export default Createrisk;
Tablepage.jsx
:
function Tablepage() {
const risksfromstorage = JSON.parse(localStorage.getItem("allrisks"));
const columns = [
{ field: "id", headerName: "ID", width: 350 },
{ field: "rname", headerName: "Risk Name", width: 350 },
{ field: "rdesc", headerName: "Risk Desc", width: 350 },
{ field: "rimpact", headerName: "Risk Impact", width: 350 },
{ field: "test", headerName: "test", width: 350 },
];
const rows = risksfromstorage.map((row) => ({
id: row.id,
rname: row.rname,
rdesc: row.rdesc,
rimpact: row.rimpact,
test: row.test,
}));
return (
<div>
<DataGrid getRowId={(row) => row.id} columns={columns} rows={rows} />
</div>
);
}
export default Tablepage;
As one can see, the Array/Object gets added to localstorage. Only the non-input attributes are populated in the table (ID & Test)
Img showing Table and LocalStorage
Share Improve this question edited Mar 16 at 20:32 Drew Reese 204k18 gold badges245 silver badges273 bronze badges asked Mar 16 at 15:07 Aleks3000Aleks3000 315 bronze badges 01 Answer
Reset to default 0It appears that the "allrisks"
data value stored in localStorage is your source of truth. Instead of attempting to work with localStorage directly, create a state in a common ancestor component that is initialized from localStorage and pass the state down as props to these two components. When the state is updated this will trigger a React component re-render.
Example:
const CommonAncestor = () => {
// Lazy initialize state from localStorage
const [allRisks, setAllRisks] = React.useState(() => {
return JSON.parse(localStorage.getItem("allrisks")) || [];
});
// Side-effect to persist state to localStorage
React.useEffect(() => {
localStorage.setItem("allrisks", JSON.stringify(allRisks));
}, [allRisks]);
// Handler to update state
const addRisk = (risk) => {
setAllRisks(allRisks => allRisks.concat(risk));
};
return (
<>
...
<CreateRisk addRisk={addRisk} />
...
<TablePage rows={allRisks} />
...
</>
);
};
CreateRisk.jsx
import { nanoid } from 'nanoid';
function CreateRisk({ addRisk }) {
function handleSubmission() {
addRisk({
id: nanoid(),
riskname: document.getElementById("rname").value,
riskdesc: document.getElementById("rdesc").value,
riskimpact: document.getElementById("rimpact").value,
test: "test",
});
}
return (
<div>
<input type="text" id="rname" placeholder="Risk Name" />
<input type="text" id="rdesc" placeholder="Risk Description" />
<input type="text" id="rimpact" placeholder="Risk Impact" />
<button onClick={handleSubmission}>Store my data</button>
</div>
);
}
TablePage.jsx
const columns = [
{ field: "id", headerName: "ID", width: 350 },
{ field: "rname", headerName: "Risk Name", width: 350 },
{ field: "rdesc", headerName: "Risk Desc", width: 350 },
{ field: "rimpact", headerName: "Risk Impact", width: 350 },
{ field: "test", headerName: "test", width: 350 },
];
function TablePage({ rows }) {
return (
<div>
<DataGrid
getRowId={(row) => row.id}
columns={columns}
rows={rows}
/>
</div>
);
}