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