admin管理员组

文章数量:1389754

I have two files/components:

  • Createrisk.jsx for creating individual risks
  • Tablepage.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 risks
  • Tablepage.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 0
Add a comment  | 

1 Answer 1

Reset to default 0

It 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>
  );
}

本文标签: javascriptHow to rerender table to reflect input dataStack Overflow