How can I get my React component to trigger a fetch when another component is used?

47 Views Asked by At

I have a React project. Initially I was fetching the data I want to display on a component straight from the directory and that was working well.

I have now added an endpoint that returns the data and I am calling the fetch method within my AdminPage component as follows:

const [projects, setProjects] = useState([]);

    const fetchProjects = async () => {
        try {
            const response = await fetch('http://localhost:3002/api/projects');
            if (!response.ok) {
                throw new Error('Failed to fetch projects');
            }
            const data = await response.json();
            setProjects(data.projects);
        } catch (error) {
            console.error('Error fetching projects:', error);
        }
    };

    useEffect(() => {
        fetchProjects();
    }, []);

This is rendering fine.

My JSON has this format:

{
  "projects": [
    {
      "projectId": "dc1f9e5d-9863-4db0-afc4-faa80ccb0320",
      "projectName": "F"
    },
    {
      "projectId": "9eff3734-a592-43ef-8b9a-63d496ea4375",
      "projectName": "O"
    }
  ]
}

I have another component, AddNewProjectWindow, that adds a project (through a POST request).

const handleConfirm = async () => {
    try {
      const response = await fetch('http://localhost:3002/api/projects', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({ projectName }),
      });
      const result = await response.json();
      if (response.ok) {
        console.log(result.message);
      } else {
        console.error('Failed to add project:', response.status, response.statusText);
      }
    } catch (error) {
      console.error('Error:', error);
    }
    onClose();
  };

Whenever the user uses such component to add a project, 'projects' becomes an empty array and therefore does no longer render.

If I then refresh the page, it renders correctly (with the added project included).

Any suggestions on how I can get projects to render correctly at all times? Including immediately after adding a project (without the need to refresh the page).

Many thanks in advance

I am using Zustand to handle state for other purposes in my application. I have tried moving the state of projects there so I can access it globally, but I don't seem to be able to make it work.

1

There are 1 best solutions below

0
Nijat Mursali On

I didn't use Zustand, but it should be same as Redux or any other state management tool. I would just return the data from API, or update the state using hooks.

// Get a hook function
const {useState} = React;

const Child = ({projects, setProjects}) => {
  const [text, setText] = useState("");

  const handleSubmit = () => {
    const newProject = {
      projectId: "new_id",
      projectName: text,
    };
    
    // here you can call the API and set the projects from response
    // or can use the updated hook and when you add new object, it will use your API to return projects
    setProjects([...projects, newProject]);
  };
  return (
    <div>
      <input
        type="text"
        value={text}
        onChange={(e) => setText(e.target.value)}
      />
      <button onClick={handleSubmit}>Submit</button>
    </div>
  );
};

const App = () => {
  const [updated, setUpdated] = useState(false);
  const [projects, setProjects] = useState([
    {
      projectId: "dc1f9e5d-9863-4db0-afc4-faa80ccb0320",
      projectName: "F",
    },
    {
      projectId: "9eff3734-a592-43ef-8b9a-63d496ea4375",
      projectName: "O",
    },
  ]);
  
    return (
        <div>
          <Child projects={projects} setProjects={setProjects} />
          {projects.map((project) => (
            <div key={project.projectId}>{project.projectName}</div>
          ))}
        </div>
    );
};

// Render it
ReactDOM.createRoot(
    document.getElementById("root")
).render(
    <App  />
);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.js"></script>