I have a component with create a blog. It works fine and navigates me to the home after adding the new blog object in the database, but I have to refresh the page to be able to see the updated data. So how can I see the updated blogs after navigation without refreshing the page?
import { useState } from "react";
import { useNavigate } from "react-router-dom";
export const Create = () => {
const [title, setTitle] = useState("");
const [body, setbody] = useState("");
const [author, setAuthor] = useState("mario");
const [isPending, setPending] = useState(false);
const nav = useNavigate();
const newBlog = { title, body, author };
const handelSubmit = (e) => {
e.preventDefault();
console.log(title);
console.log(body);
console.log(author);
setPending(true);
fetch("http://localhost:3001/blogs", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(newBlog),
}).then(() => {
console.log("newBlog Added");
setPending(false);
nav("/");
});
console.log(newBlog);
};
return (
<div className="create">
<h2>Add a New Blog</h2>
<form onSubmit={handelSubmit}>
<label htmlFor="">Blog title:</label>
<input
type="text"
required
value={title}
onChange={(e) => setTitle(e.target.value)}
/>
<label htmlFor="">Blog Body:</label>
<textarea
required
value={body}
onChange={(e) => setbody(e.target.value)}
></textarea>
<label htmlFor="">Blog author:</label>
<select value={author} onChange={(e) => setAuthor(e.target.value)}>
<option value="mario">Mario</option>
<option value="magdy">Magdy</option>
</select>
{!isPending && <button>Add Blog</button>}
{isPending && <button disabled>Adding Blog</button>}
</form>
</div>
);
};
//Home component implementation
import React from "react";
import Blog from "./../blog/Blog";
export const Home = () => {
// const { data, flag, error } = useFetch("http://localhost:3001/blogs");
const [blogs, setBlogs] = useState(null);
const [flag, setFlag] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
fetch("http://localhost:3001/blogs")
.then((res) => {
if (!res.ok) {
throw Error("Error in the API");
}
return res.json();
})
.then((data) => {
console.log(data);
setBlogs(data);
setFlag(!flag);
})
.catch((e) => {
console.log(e.message);
setError(e.message);
setFlag(!flag);
});
return () => {};
}, []);
return (
<div className="home">
{blogs && <Blog blogs={blogs} title="All Blogs" />}
{flag && <p>Loading...</p>}
{error !== null && <p>{error}</p>}
</div>
);
};
//Blog component implementation
import React from "react";
import { Link, Route, Routes } from "react-router-dom";
import { BlogDetails } from "../BlogDetails/BlogDetails";
import { Create } from "../create/Create";
import { Error } from "../Notfound/Error";
function Blog({ blogs, title }) {
return (
<Routes>
<Route
path="/"
element={
<div>
<h2>{title}</h2>
{blogs.map((blog) => {
return (
<div className="blog" key={blog.id}>
<Link to={`blogs/${blog.id}`}>
<h3>{blog.title}</h3>
<p>{blog.body}</p>
<h6>Written By {blog.author}</h6>
</Link>
</div>
);
})}
</div>
}
></Route>
<Route path="/create" element={<Create />}></Route>
<Route path="/blogs/:id" element={<BlogDetails />}></Route>
<Route path="*" element={<Error />}></Route>
</Routes>
);
}
export default Blog;
Advertisement
Answer
In order to update the blogs state, which is declared at the main point of the application, which is, for example, App.jsx, you must pass the state blogs and the set-state-action setBlogs as properties to the child component. For example:
The state in App.jsx:
const [blogs, setBlogs] = useState(null)
The child component (on which you will update the blogs state):
<Create blogs={blogs} setBlogs={setBlogs} />
On the fetch‘s then
fetch("http://localhost:3001/blogs", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(newBlog),
}).then((data) => {
console.log("newBlog Added");
setPending(false);
setBlogs([...blogs, newBlog])
nav("/");
});
console.log(newBlog);