Компонент не выполняет повторную визуализацию при обновлении State с использованием реакции, приращения и погружения. - PullRequest
0 голосов
/ 18 марта 2020

У меня есть простой код, который содержит компонент PostFeed для отображения каналов и компонент PostItem внутри него, который показывает каждый канал. в PostItem пользователь может делать лайк-фид, а здесь сервисный звонок и количество лайков изменится. если текущему пользователю понравился канал, у большого пальца будет синий цвет.

все прекрасно работает при обновлении страницы, но когда каналу нравится или не нравится, состояние получает обновление и количество лайков изменилось верно, но цвет компонента не меняется. Для того чтобы навсегда предотвратить это, я использовал Immer .

Вот код

//PostFeed Component
class PostFeed extends Component {
  render() {
    const { posts } = this.props;

    return posts && posts.map(post => <PostItem key={post._id} post={post} />);
  }
}

//PostItem Component
class PostItem extends Component {

  componentWillReceiveProps(nextProps) {
    if (nextProps.post) {
      this.setState({ post: nextProps.post });
        }
      }

  onLikeClick(id) {
    this.props.addLike(id);
  }

  isCurrentUserLike(likes: ILike[]) {
    const { auth } = this.props;
    if (likes.filter(like => like.user === (auth.user as any).id).length > 0) {
      return <i className="fas fa-thumbs-up text-info" />;
    } else {
      return <i className="fas fa-thumbs-up" />;
    }
  }

render() {
const { post, auth } = this.props;
return (
      <div className="card card-body mb-3">

...

<button onClick={this.onLikeClick.bind(this, post._id)} type="button" className="btn btn-light mr-1">

        // This line does not re-render                 
        {this.isCurrentUserLike(post.likes)}

       <span className="badge badge-light">{post.likes.length}</span>
    </button>
      }
    }

const mapStateToProps = (state) => ({
  auth: state.auth
});

export default connect(mapStateToProps, { addLike})(
  PostItem
);

это действие:

export const addLike = (id) => (dispatch) => {
  axios
    .post(`/api/posts/like/${id}`)
    .then(res =>
      dispatch({
        type: "POST_LIKED",
        payload: res.data
      })
    )
    .catch(err =>
      dispatch({
        type: "GET_ERRORS",
        payload: err.response.data
      })
    );
};

и это редуктор:

export default (state = initialState, action) => {
  return produce(state, (draft): any => {
    switch (action.type) {

 case "POST_LIKED":
        draft.posts = substitudePost(draft.posts, action.payload);
        draft.loading = false;
        break;
}}
    )}

const substitudePost = (posts, post) => {
  const index = posts.findIndex(i => i._id == post._id);
  if (index > -1) posts[index] = post;
  return posts;
}

и это типы данных:

 interface initialFeedState= {
  posts: IPost[],
  post: IPost,
  loading: false
};

interface IPost  {
  _id: string;
  user: IUser;
  likes: ILike[];
  comments: IComment[];
  date: string;
}

1 Ответ

0 голосов
/ 18 марта 2020

Я думаю, что проблема в этой строке

if (likes.filter(like => like.user === (auth.user as any).id).length > 0) {

Вы сравниваете пользователя объект с аутентифицированным пользователем id , они никогда не будут одинаковыми. И вы можете использовать такую ​​функцию, как это

if (likes.some(like => like.user.id === auth.user.id)) {
...