英文:
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>
)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论