我有一个子组件PostItem
,该子组件将来自redux状态的post对象作为道具:
const PostItem = ({
post: { _id, text, name, avatar, user, likes}, //from redux state
//...
}) => {
//...
const handleLike = e => {
likePost(_id); //ACTION
};
return (
<Fragment>
<div className='post bg-white vert-m-1 p-1'>
<div>
<p className='vert-m-1'>{text}</p>
<button className='btn' onClick={e => handleLike(e)}>
<i className='fas fa-thumbs-up'></i> <span>{likes.length}</span>
</button>
</div>
</Fragment>
);
}
我有一个操作likePost
更改了reducer
中的状态:
case LIKE_A_POST:
case UNLIKE_A_POST:
return {
...state,
posts: state.posts.map(post =>
post._id === payload.id
? {
...post,
likes: payload.likes
}
: post
),
loading: false
};
据我所知,React组件会在状态或道具更改时重新呈现。
我从两个父组件PostItem
和Posts
渲染子组件Comment
。
如果从PostItem
渲染了Posts
,则触发动作likePost
将自动重新渲染组件。这是有道理的,因为我的redux状态更改了,这将导致重新渲染。另外,由于将redux状态作为道具传递给PostItem
,所以更改redux状态将更改道具,这也会触发重新渲染。
但是,从PostItem
渲染Comment
时,即使likePost
动作仍然改变了我的位置,触发PostItem
并不会导致likePost
重新渲染还原状态。我可以在redux Developer工具中看到状态实际上已更改,但是未触发重新渲染。在这种情况下,也将redux状态作为prop传递给PostItem
,但是prop的更改不会触发重新渲染。
为什么在PostItem
父组件中而不是在Posts
父组件中重新渲染Comment
? Posts
和Comment
都传递一个post对象(包含我的redux状态)作为对PostItem
的支持。
根据在线建议,我的化简使用散布运算符来避免使用相同的对象引用。 Posts
和Comment
都使用相同的操作来更改我的redux状态,这意味着两种情况下状态都在变化。 Posts
和Comment
都将redux状态作为对PostItem
的支持,这意味着在两种情况下道具都被更改了。
对于完整的可复制代码,我不确定该如何进行 涉及访问数据库,需要我的数据库URI以及 JSON秘密Web令牌。就如何提供最低限度的建议, 请复制示例。
指向我的仓库的链接:https://github.com/boxcarcoder/ExplorersConnect
请在
reprex
分支中查看的最低版本 以下文件:PostItem,Posts和Comment组件:explorersConnect / client / src / components / posts
动作:explorersConnect /客户端/ src /动作
Reducers:explorersConnect /客户端/ src / reducers
答案 0 :(得分:0)
关键是要认识到,尽管likePost
更改了帖子的likes
,但该帖子不是post
的redux状态,而是posts
数组内的帖子还原状态。这意味着触发likePost
会触发对posts
的更改,这是对Posts
的支持,而不是Comment
的支持。错误的假设是,更改Posts
会导致状态更改,从而触发Comment
重新渲染,但是Comment
的道具不会更改,因此没有重新渲染。>
由于Comment
的道具为post
,因此likePost
的动作和减速器应在还原状态下更改post
,以便触发道具和状态的更改重新渲染Comment
。
更改状态之间存在混淆:
更改state.posts
与更改state.post
并不相同,尽管从理论上讲state.posts
只是所有state.post
的数组。关键是要理解,必须更改组件的Props,而不仅仅是状态更改。状态更改必须直接影响组件的道具。