Skip to content
Advertisement

How can I update or re-render a component from another component? (React)

I originally had two components displayed on two different pages via Routes: the RecordList and Create components. It all currently works properly when I use Routes. However, I’m trying to modify this project so that both components are on the same page at the same time instead of being on two different pages.

My goal is to have RecordList update (fetch the data from the server) once I click the “Add Record” button. Currently the Create component is working properly, however I have to refresh the page to see the changes on the RecordList component.

I’m having trouble understanding what I need to do to get RecordList to update when the record is posted to the server. Any guidance is helpful.

Would this be a scenario to use Lifting Up State? I didn’t think so because I believe these two components are sibling components.

Do I need to re-render the RecordList component? Should I just combine these two components into one component? My guess was that it would be better for these to be two separate components.

For reference, I did not write all of this code. I’m trying to modify the project I built using the MERN tutorial on the MongoDB website.

Here is a screenshot of the page: homepage

App.js:

import React from "react";
import './App.css';

// We use Route in order to define the different routes of our application
import { Route, Routes } from "react-router-dom";

// We import all the components we need in our app
import Navbar from "./components/navbar";
import RecordList from "./components/recordList";
import Edit from "./components/edit";
import Create from "./components/create";

const App = () => {
    return (
        <div>
            <div className="container">
                <Navbar />
            </div>
            <div className="container py-3 my-3 d-flex align-items-start justify-content-around flex-wrap flex-md-nowrap">

                <div className="w-100 px-md-3 py-3 py-md-0"><RecordList /></div>
                <div className="w-100 px-md-3 py-3 py-md-0"><Create /></div>
                {/* <Routes>
                    <Route exact path="/" element={<RecordList />} />
                    <Route path="/edit/:id" element={<Edit />} />
                    <Route path="/create" element={<Create />} />
                </Routes> */}
            </div>
        </div>
    );
};

export default App;

recordList.js:

import React, { useEffect, useState } from "react";
import { Link } from "react-router-dom";

const Record = (props) => (
    <tr>
        <td>{props.record.date}</td>
        <td>{props.record.destination}</td>
        <td>{props.record.location}</td>
        <td>
            <Link className="btn btn-link" to={`/edit/${props.record._id}`}>Edit</Link> |
            <button className="btn btn-link"
                onClick={() => {
                    props.deleteRecord(props.record._id);
                }}
            >
                Delete
            </button>
        </td>
    </tr>
);

export default function RecordList() {
    const [records, setRecords] = useState([]);

    // This method fetches the records from the database.
    useEffect(() => {
        async function getRecords() {
            const response = await fetch(`http://localhost:5000/record/`);

            if (!response.ok) {
                const message = `An error occurred: ${response.statusText}`;
                window.alert(message);
                return;
            }

            const records = await response.json();
            setRecords(records);
        }

        getRecords();

        return;
    }, [records.length]);

    // This method will delete a record
    async function deleteRecord(id) {
        await fetch(`http://localhost:5000/${id}`, {
            method: "DELETE"
        });

        const newRecords = records.filter((el) => el._id !== id);
        setRecords(newRecords);
    }

    // This method will map out the records on the table
    function recordList() {
        return records.map((record) => {
            return (
                <Record
                    record={record}
                    deleteRecord={() => deleteRecord(record._id)}
                    key={record._id}
                />
            );
        });
    }

    // This following section will display the table with the records of individuals.
    return (
        <div>
            <h3>Record List</h3>
            <table className="table table-striped" style={{ marginTop: 20 }}>
                <thead>
                    <tr>
                        <th>Date</th>
                        <th>Destination</th>
                        <th>Location</th>
                        <th>Action</th>
                    </tr>
                </thead>
                <tbody>{recordList()}</tbody>
            </table>
        </div>
    );
}

create.js:

import { useNavigate } from "react-router";

export default function Create() {
    const [form, setForm] = useState({
        date: "",
        destination: "",
        location: "",
    });
    const navigate = useNavigate();

    // These methods will update the state properties.
    function updateForm(value) {
        return setForm((prev) => {
            return { ...prev, ...value };
        });
    }

    // This function will handle the submission.
    async function onSubmit(e) {
        e.preventDefault();

        // When a post request is sent to the create url, we'll add a new record to the database.
        const newPerson = { ...form };

        await fetch("http://localhost:5000/record/add", {
            method: "POST",
            headers: {
                "Content-Type": "application/json",
            },
            body: JSON.stringify(newPerson),
        })
            .catch(error => {
                window.alert(error);
                return;
            });

        setForm({ date: "", destination: "", location: "" });
        navigate("/");
    }

    // This following section will display the form that takes the input from the user.
    return (
        <div>
            <h3>Add Mileage Record</h3>
            <form onSubmit={onSubmit}>
                <div className="row my-3">
                    <div className="col">
                        <div className="form-group">
                            <label htmlFor="date">Date</label>
                            <input
                                type="text"
                                className="form-control"
                                id="date"
                                value={form.date}
                                onChange={(e) => updateForm({ date: e.target.value })}
                            />
                        </div>
                    </div>
                    <div className="col">
                        <div className="form-group">
                            <label htmlFor="destination">Destination</label>
                            <input
                                type="text"
                                className="form-control"
                                id="destination"
                                value={form.destination}
                                onChange={(e) => updateForm({ destination: e.target.value })}
                            />
                        </div>
                    </div>
                </div>
                <div className="row my-3">
                    <div className="col">
                        <div className="form-group">
                            <label htmlFor="location">Location</label>
                            <input
                                type="text"
                                className="form-control"
                                id="location"
                                value={form.location}
                                onChange={(e) => updateForm({ location: e.target.value })}
                            />
                        </div>
                    </div>
                    <div className="row my-3">
                        <div className="col">
                            <div className="form-group">
                                <input
                                    type="submit"
                                    value="Add Record"
                                    className="btn btn-primary"
                                />
                            </div>
                        </div>
                    </div>
                </div>
            </form>
        </div>
    );
}

Advertisement

Answer

you have several ways to solve this problem:

  1. you can move records state from recordList to App and pass records to recordList component and pass setRecords to create component as props, so you can update records when statusCode of http://localhost:5000/record/add is 200.

  2. you can use stateManagement packages like redux, redux-toolkit, jotai, … to has a manager to manage changes on the entire application side

  3. you can use context for save records to access records everywhere in the application.

  4. you can use react-query package to manage get and save data together. you can react-query-useful-hooks for optimal and easier use of rickett

User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement