英文:
Parent component rerender useEffect
问题
I have a parent Component named Posts that has a useEffect and fetches data, then I have a child component named Post which renders the post from props. I have a delete and like function inside Post and I want the parent to rerender when post gets liked or post gets deleted. How can I achieve this?
const Posts = () => {
const [posts, setPosts] = useState([]);
useEffect(() => {
getPosts();
}, []);
const getPosts = async () => {
const data = await fetch('https://localhost:1111/api/posts/posts', {
credentials: 'include'
});
const response = await data.json();
console.log(response);
setPosts(response);
};
return (
<div>
{posts.map(post => (
<Post key={post.id} post={post} />
))}
</div>
);
};
const Post = props => {
const like = async post => {
const formData = new FormData();
formData.append('id', post);
const data = await fetch('https://localhost:1111/api/posts/like', {
method: 'POST',
body: formData,
credentials: 'include'
});
const response = await data.json();
console.log(response);
};
const deletePost = async post => {
const formData = new FormData();
formData.append('id', post);
const data = await fetch('https://localhost:1111/api/posts/deletepost', {
method: 'POST',
body: formData,
credentials: 'include'
});
const response = await data.json();
console.log(response);
};
return (
<div>
<img
src={`http://localhost:1111/api/posts/uploads/images/${props.post.content}`}
alt={`Post ${props.post.id}`}
/>
<button onClick={() => like(props.post.id)}>Like</button>
<button onClick={() => deletePost(props.post.id)}>Delete</button>
</div>
);
};
英文:
I have a parent Component named Posts that has a useEffect and fetches data, then I have a child component named Post which renders the post from props. I have a delete and like function inside Post and I want the parent to rerender when post get liked or post gets deleted. How can I achieve this?
const Posts = () => {
const [posts, setPosts] = useState([]);
useEffect(() => {
getPosts();
}, []);
const getPosts = async () => {
const data = await fetch('https://localhost:1111/api/posts/posts', {
credentials: 'include'
});
const response = await data.json();
console.log(response);
setPosts(response);
};
return (
<div>
{posts.map(post => (
<Post key={post.id} post={post} />
))}
</div>
);
};
const Post = props => {
const like = async post => {
const formData = new FormData();
formData.append('id', post);
const data = await fetch('https://localhost:1111/api/posts/like', {
method: 'POST',
body: formData,
credentials: 'include'
});
const response = await data.json();
console.log(response);
};
const deletePost = async post => {
const formData = new FormData();
formData.append('id', post);
const data = await fetch('https://localhost:1111/api/posts/deletepost', {
method: 'POST',
body: formData,
credentials: 'include'
});
const response = await data.json();
console.log(response);
};
return (
<div>
<img
src={`http://localhost:1111/api/posts/uploads/images/${props.post.content}`}
alt={`Post ${props.post.id}`}
/>
<button onClick={() => like(props.post.id)}>Like</button>
<button onClick={() => deletePost(props.post.id)}>Delete</button>
</div>
);
};
答案1
得分: 1
I would recommend you to have an additional prop method (onUpdate) on the child <Post /> component, which gets triggered whenever the deletePost() or like() are triggered.
const Posts = () => {
const [posts, setPosts] = useState([]);
useEffect(() => {
getPosts();
}, []);
const getPosts = async () => {
const data = await fetch('https://localhost:1111/api/posts/posts', {
credentials: 'include'
});
const response = await data.json();
console.log(response);
setPosts(response);
};
const handleUpdate = () => {
getPosts();
}
return (
<div>
{posts.map(post => (
<Post key={post.id} onUpdate={() => handleUpdate()} post={post} />
))}
</div>
);
};
const Post = props => {
const { onUpdate } = props;
const like = async post => {
const formData = new FormData();
formData.append('id', post);
const data = await fetch('https://localhost:1111/api/posts/like', {
method: 'POST',
body: formData,
credentials: 'include'
});
const response = await data.json();
console.log(response);
onUpdate();
};
const deletePost = async post => {
const formData = new FormData();
formData.append('id', post);
const data = await fetch('https://localhost:1111/api/posts/deletepost', {
method: 'POST',
body: formData,
credentials: 'include'
});
const response = await data.json();
console.log(response);
onUpdate();
};
return (
<div>
<img
src={`http://localhost:1111/api/posts/uploads/images/${props.post.content}`}
alt={`Post ${props.post.id}`}
/>
<button onClick={() => like(props.post.id)}>Like</button>
<button onClick={() => deletePost(props.post.id)}>Delete</button>
</div>
);
};
As you can see, onUpdate() is called at the end of both deletePost() and like(), and on the parent Posts component, handleUpdate() will be called, which in turn submits the fetch response to update the posts state. This will cause the parent <Posts /> to re-render.
英文:
I would recommend you to have an additional prop method (onUpdate) on the child <Post /> component, which gets triggered whenever the deletePost() or like() are triggered.
const Posts = () => {
const [posts, setPosts] = useState([]);
useEffect(() => {
getPosts();
}, []);
const getPosts = async () => {
const data = await fetch('https://localhost:1111/api/posts/posts', {
credentials: 'include'
});
const response = await data.json();
console.log(response);
setPosts(response);
};
const handleUpdate = () => {
getPosts();
}
return (
<div>
{posts.map(post => (
<Post key={post.id} onUpdate={() => handleUpdate()} post={post} />
))}
</div>
);
};
const Post = props => {
const { onUpdate } = props;
const like = async post => {
const formData = new FormData();
formData.append('id', post);
const data = await fetch('https://localhost:1111/api/posts/like', {
method: 'POST',
body: formData,
credentials: 'include'
});
const response = await data.json();
console.log(response);
onUpdate();
};
const deletePost = async post => {
const formData = new FormData();
formData.append('id', post);
const data = await fetch('https://localhost:1111/api/posts/deletepost', {
method: 'POST',
body: formData,
credentials: 'include'
});
const response = await data.json();
console.log(response);
onUpdate();
};
return (
<div>
<img
src={`http://localhost:1111/api/posts/uploads/images/${props.post.content}`}
alt={`Post ${props.post.id}`}
/>
<button onClick={() => like(props.post.id)}>Like</button>
<button onClick={() => deletePost(props.post.id)}>Delete</button>
</div>
);
};
As you can see, onUpdate() is called at the end of both deletePost() and like(), and on the parent Posts component, handleUpdate() will be called, which in turn submits the fetch response to update the posts state. This will cause the parent <Posts /> to re-render.
答案2
得分: 0
Keep post functionality inside the parent component and pass the update functions to Post
const Posts = () => {
const [posts, setPosts] = useState([])
useEffect(() => {
fetch('https://localhost:1111/api/posts/posts', {
credentials: 'include',
})
.then(res => res.json())
.then(setPosts)
}, [])
const likePost = async postId => {
await fetch...
setPosts(prevState =>
prevState.map(post =>
post.id === postId
? {
...post,
likes: post.likes + 1,
}
: post
)
)
}
const deletePost = async postId => {
await fetch...
setPosts(prevState => prevState.filter(post => post.id !== postId))
}
return (
<div>
{posts.map(post => (
<Post
key={post.id}
post={post}
likePost={likePost}
deletePost={deletePost}
/>
))}
</div>
)
}
const Post = ({ post, likePost, deletePost }) => (
<div>
<img
src={`http://localhost:1111/api/posts/uploads/images/${post.content}`}
alt={`Post ${post.id}`}
/>
<button onClick={() => likePost(post.id)}>Like</button>
<button onClick={() => deletePost(post.id)}>Delete</button>
</div>
)
英文:
Keep post functionality inside the parent component and pass the update functions to Post
const Posts = () => {
const [posts, setPosts] = useState([])
useEffect(() => {
fetch('https://localhost:1111/api/posts/posts', {
credentials: 'include',
})
.then(res => res.json())
.then(setPosts)
}, [])
const likePost = async postId => {
await fetch...
setPosts(prevState =>
prevState.map(post =>
post.id === postId
? {
...post,
likes: post.likes + 1,
}
: post
)
)
}
const deletePost = async postId => {
await fetch...
setPosts(prevState => prevState.filter(post => post.id !== postId))
}
return (
<div>
{posts.map(post => (
<Post
key={post.id}
post={post}
likePost={likePost}
deletePost={deletePost}
/>
))}
</div>
)
}
const Post = ({ post, likePost, deletePost }) => (
<div>
<img
src={`http://localhost:1111/api/posts/uploads/images/${post.content}`}
alt={`Post ${post.id}`}
/>
<button onClick={() => likePost(post.id)}>Like</button>
<button onClick={() => deletePost(post.id)}>Delete</button>
</div>
)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论