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.
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} />