useSelector 在状态改变时不会重新渲染组件

时间:2021-01-08 16:05:40

标签: javascript reactjs typescript redux state

我正在开发一个新闻聚合器,我有一个 Newsfeed 组件可以映射相关帖子并为每个帖子创建一个 Post 组件。有一个 Sidebar 组件向用户显示他们订阅的提要,并允许他们订阅新提要或取消订阅现有提要。我希望发生的是:

  1. 当用户添加新供稿时,Newsfeed 会重新呈现并显示来自新供稿的帖子。
  2. 当用户移除一个供稿时,Newsfeed 会重新呈现并且不再显示来自该特定供稿的帖子。

至于检索正确的帖子 - 我的后端负责处理,并且工作正常。后端根据用户订阅的提要返回帖子。问题是,当用户添加或删除提要时,Newsfeed 组件不会重新呈现,并且需要重新加载页面才能显示更新的提要。然而与此同时,Redux 商店也更新了,我每次都可以通过 Redux Dev Tools 看到状态变化。

Newsfeed 中,我使用 useSelector 钩子来获取几个不同的状态片段,但是当状态改变时组件不会重新渲染。我的印象是,任何使用 useSelector 钩子的组件都会在状态改变时自动重新渲染,但如果钩子不是这样工作的,请纠正我。

Newsfeed.tsx

import React, { useState, useRef, useCallback } from "react";
import usePostFetch from "../hooks/usePostFetch";
import { Post } from "./Post";
import { Tag } from "./Tag";
import { Upvote } from "./Upvote";
import { getDate } from "../services/getDate";
import { useSelector } from "react-redux";
import { InitialState } from "../store/reducers/rootReducer";

export const Newsfeed = (props: any) => {

  const userState = useSelector((state: InitialState) => {
    return state.auth;
  });

  const { user } = userState;

  const publisherState = useSelector((state: InitialState) => {
    return state.publishers.publishers;
  });

  const [pageNumber, setPageNumber] = useState(1);

  const { loading, error, posts, hasMore } = usePostFetch(pageNumber);

  const observer: any = useRef();
  const lastPostElementRef = useCallback(
    (node) => {
      if (loading) return;
      if (observer && observer.current) observer.current.disconnect();
      observer.current = new IntersectionObserver((entries) => {
        if (entries[0].isIntersecting && hasMore) {
          console.log("Visible ");
          setPageNumber((prevPageNumber) => prevPageNumber + 1);
        }
      });
      if (node) observer.current.observe(node);
      console.log(node);
    },
    [loading, hasMore]
  );

  return (
    <div className="container mx-auto bg-gray-900" id="newsfeed">
      <div className="object-center grid grid-cols-1 gap-8 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 mx-auto pb-6 pt-6">
        
        {posts.map((post, index) => {
          return (
            <Post
              key={post.id}
              title={post.title}
              url={post.url}
              image={post.image}
              category={post.category}
              postId={post._id}
              created={post.created}
              publisher={post.publisher}
              upvotes={post.upvotes}
            />
          );
        })}
      </div>
      <div>{loading && "Loading..."}</div>
      <div>{error && "Error"}</div>
    </div>
  );
};

publisherActions.ts:(相关部分)

export const removeFeed = (allFeeds: any, feedName: any, userId: any) => async (
  dispatch: Dispatch<PublisherDispatchTypes>
) => {
  try {
    axios({
      method: "PUT",
      url: "users/removepublisher",
      params: { publisher: feedName, userId },
    })
      .then((res) => {
        let newAllFeeds = allFeeds.filter((feed: any) => {
          return feed.name.localeCompare(feedName) !== 0;
        });

        allFeeds = newAllFeeds;

        console.log(`Feed was removed, ${res}`);
        dispatch({
          type: REMOVE_FEED_SUCCESS,
          payload: allFeeds,
        });
      })
      .catch((err) => {
        console.log(`Error removing feed, ${err}`);
        dispatch({
          type: REMOVE_FEED_FAILURE,
        });
      });
  } catch {
    dispatch({ type: REMOVE_FEED_FAILURE });
    console.log("Caught error while removing feed");
  }
};

export const addFeed = (allFeeds: any, feed: any, userId: any) => async (
  dispatch: Dispatch<PublisherDispatchTypes>
) => {
  console.log("IN THE ADD_FEED FUNCTION");
  try {
    axios({
      method: "PUT",
      url: "users/addpublisher",
      params: { publisher: feed, userId },
    })
      .then((res) => {

        console.log(`Feed was added, ${res}`);
        dispatch({
          type: ADD_FEED_SUCCESS,
          payload: {
            name: feed.name,
            url: feed.url,
            image: feed.image,
          },
        });
      })
      .catch((err) => {
        console.log(`Error adding feed, ${err}`);
        dispatch({
          type: ADD_FEED_FAILURE,
        });
      });
  } catch {
    dispatch({ type: ADD_FEED_FAILURE });
    console.log("Caught error while adding feed");
  }

publisherReducer.ts:(相关部分)

import { Reducer } from "react";
import {
  PublisherDispatchTypes,
  REMOVE_FEED_SUCCESS,
  REMOVE_FEED_FAILURE,
  ADD_FEED_SUCCESS,
  ADD_FEED_FAILURE,
} from "../actions/publisherActionsTypes";
import { Publisher } from "../../../../shared/Publisher";

interface PublisherResponse {
  publishers: Publisher[];
}

export interface PublisherState {
  publishers: Publisher[] | undefined;
  loadedUsersFeeds: boolean;
  feedCount: number;
}

const defaultState: PublisherState = {
  publishers: undefined,
  loadedUsersFeeds: false,
  feedCount: 0,
};

const publisherReducer = (
  state: PublisherState = defaultState,
  action: PublisherDispatchTypes
) => {
  switch (action.type) {
    case REMOVE_FEED_SUCCESS:
      return {
        ...state,
        publishers: action.payload,
      };
    case REMOVE_FEED_FAILURE:
      return state;
    case ADD_FEED_SUCCESS:
      let pubs = state.publishers || [];
      return {
        ...state,
        publishers: [...pubs, action.payload],
      };
    case ADD_FEED_FAILURE:
      return state;
    default:
      return state;
  }
};

export default publisherReducer;

0 个答案:

没有答案