Search code examples
reactjsreact-state-management

React: fetch updated data from server without refresh


Suppose my React component structure looks as follows:

App
|-PostList
|-CreatePost

In PostList component I populate my state by fetching data from a server like:

...
 const [posts, setPosts] = useState({});
  useEffect(() => {
    async function fetchPosts() {
      try {
        const res = await axios.get(`${BACKEND_API}/posts`)
        await setPosts(res.data)
      } catch (e) {
        console.log(e)
      }
    }
    fetchPosts()
  }, []);

And render those posts. Again, in my CreatePost component I create a new post and sent those data to the server like this:

...
  const [title, setTitle] = useState('');
  const submitHandler = async (e) => {
    e.preventDefault();
    await axios.post(`${BACKEND_API}/posts/create`, { title });
    setTitle('')
  };
...

Now there the problem arise. I can't see my new post without refreshing the page. I try to solve this problem like lifting state up in the App component and pass the setPosts handler to the CreatePost component. Because I was thinking to update my posts state again inside the submitHandler like this:

    async function refreshPosts(setPosts) {
      const res = await axios.get(`${BACKEND_API}/posts`)
      await setPosts(res.data)
    }

I was confused is it the corrent way? As I heard lifting state up is not a good decision. Is there any better solution? I was trying to avoid any state management lib. Which come with a lot of extra work for this simple problem.


Solution

  • Lifting state up is a good decision until you're not drilling props for children that are 3-4 level deep.

    I recommend putting it in a container component (Post) that passes props to PostList and CreatePost though. In the future, you might have more components in your App. Then, other future components might re-render unnecessarily.

    App
    |-Post // put all your state and handlers regarding Post here
     |-PostList // use this just as plain view, just shows the list of the post
     |-CreatePost // use this just as plain view, just form to create a post
    |-FutureComponent // handles it own state, doesn't re-render when post change
    |-FutureMoreComponent // handles it own state,, doesn't re-render when post change
    

    In the above structures, your FutureComponent and FutureMoreComponent won't re-render if your Post re-renders because Post is a self-contained component.

    Your component structure might look something like this then

    PostList.js

    <PostList posts={postsStateFromPostComponent} />
    

    CreatePost.js

    <CreatePost onSubmit={apiThatCreatesANewPost} />