对此组件的使用效果
我正在尝试使用usefect来rerender postlist
(在没有删除帖子的情况下使其呈现) postScount
更改时,但我无法正确。我试图将所有内容包裹在使用效果中,但是我无法执行 addeventListener(“ click”,handingpost)
,因为我使用useffect等待该组件先安装,然后再安装extlistener。
父组件:
function Tabs() {
const [posts, setPosts] = useState([]);
const dispatch = useDispatch();
const postsCount = useSelector((state) => state.posts.count);
useEffect(() => {
document.getElementById("postsTab").addEventListener("click", handlePost);
}, [handlePost]);
const handlePost = async (e) => {
const { data: { getPosts: postData }} = await refetchPosts();
setPosts(postData);
dispatch(postActions.getPostsReducer(postData));
};
const { data: FetchedPostsData, refetch: refetchPosts } = useQuery( FETCH_POSTS_QUERY, { manual: true });
const [postList, setPostsList] = useState({});
useEffect(() => {
setPostsList(
<Tab.Pane>
<Grid>
<Grid.Column>Title</Grid.Column>
{posts.map((post) => (
<AdminPostsList key={post.id} postId={post.id} />
))}
</Grid>
</Tab.Pane>
);
console.log("changed"); //it prints "changed" everytime postCount changes (or everytime I click delete), but the component doesn't remount
}, [postsCount]);
const panes = [
{ menuItem: { name: "Posts", id: "postsTab", key: "posts" }, render: () => postList }
];
return (<Tab panes={panes} />);
}
Child/AdminPostSlist组件:
function AdminPostsList(props) {
const { postId } = props;
const [deletePost] = useMutation(DELETE_POST_MUTATION, {variables: { postId } });
const dispatch = useDispatch();
const deletePostHandler = async () => {
dispatch(postActions.deletePost(postId));
await deletePost();
};
return (
<>
<Button icon="delete" onClick={deletePostHandler}></Button>
</>
);
}
还原器
const PostSlice = createSlice({
name: "storePosts",
initialState: {
content: [],
count: 0,
},
reducers: {
getPostsReducer: (state, action) => {
state.content = action.payload;
state.count = action.payload.length
},
deletePost: (state, action) => {
const id = action.payload
state.content = current(state).content.filter((post) => (post.id !== id))
state.count--
}
},
});
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
好吧,让我们在单独的评论中讨论这一点。关键点是将帖子逻辑从包装组件(TABS)中解释。您应该仅创建专门用于帖子并将其渲染的组件。像这样,您可以轻松地将与帖子相关的组件中的所有与帖子相关的逻辑隔离,例如,避免在包装器中附加一些听众(因为它不直观您在做什么,谁在听什么,因为按钮不在同一组件中) 。在分离的组件中,您只能有一个使用效果,可以提取帖子,并且您将拥有一个选择器(从Redux中选择帖子),然后只使用该选择来从组件输出内容。
该部分
&lt; tab panes = {...}/&gt;
是您大多数问题的来源,因为这样您被迫求解上面的所有内容&lt; tab ../ &gt;
然后只是为了通过它,这不是最好的练习,因为它可能太复杂了(尤其是在您有多个选项卡时)。这就是为什么您需要解开并创建特定于选项卡的组件的原因。这将是您应该如何重构的想法:
Okay, let discuss this in separate comment. Key point is to decouple posts logic from wrapper component(Tabs). You should create component dedicated only to posts and render it in wrapper. Like that you can easily isolate all posts-related logic in posts-related component, for example to avoid attaching some listeners from wrapper(because it is not intuitive what you are doing and who listens for what because button is not in that same component). In separated component you will have only one useEffect, to fetch posts, and you will have one selector(to select posts from redux), and then just use that selection to output content from component.
That part
<Tab panes={...} />
was the source of most of your problems, because like that you are forced to solve everything above<Tab../>
and then just to pass it, which is not best practice in you case since it can be too complicated(especially in case when you could have multiple tabs). That is why you need to decouple and to create tab-specific components.This would be an idea of how you should refactor it:
好的,让我们讨论我对未来读者做错了什么:
因为我可以使用
&lt;菜单。 ;
直接连接onclick
。我必须使用
使用
来监视ports
依赖项,但是.map()
将自动更新其内容,如果数组我正在映射有任何更改,因此在此上下文中无需使用使用
我认为我可以从子组件中使用升降状态到
setPost
,更改将触发.map()
重新映射并弹出已删除的元素,但是我可以't找到一种方法,所以我使用的是redux(存储帖子)和useffect
将 ports 分配给商店,而不是我正在映射存储的redux元素,如果这是最好的方法,但这是我设法做的。我几乎尝试过的最重要的事情是,我必须使用
proxy.readquery
在添加/删除帖子时更新Apollo-cache这就是我的做法
感谢 @ anuj panwar @ milos pavlovic 帮助您提供帮助,kudos to @引起了我的注意
Ok, let's discuss what I did wrong for the future reader:
for I could've used a
<Menu.Item onClick={handleClick}>Posts</Menu.Item>
to attach theonClick
directly.I had to use
useEffect
to monitorposts
dependency, but.map()
will automatically update its content if the array I am mapping had any changes so there is no need to use it useuseEffect
in this context.I think I can use lifting state to
setPosts
from the child component and the change will trigger.map()
to remap and pop the deleted element, but I couldn't find a way to so, so I am using a combination of redux (to store the posts) anduseEffect
to dispatch theposts
to the store than I am mapping over the stored redux element, idk if this is the best approach but this is all I managed to do.The most important thing I didn't notice when I almost tried everything is, I must update apollo-cache when adding/deleting a post, by using
proxy.readQuery
this is how I did it
Thanks to @Anuj Panwar @Milos Pavlovic for helping out, kudos to @Cptkrush for bringing the store idea into my attention