React(+ Typescript)组件在更新上下文时不会重新呈现

React (+ Typescript) component not rerendering upon updating Context

我有一个 LaunchItem 组件,它使用 React.Context 获取和设置信息 to/from 本地存储。

我想要实现的是,当组件更新上下文(和本地存储)时,我希望它使用新信息重新呈现,以便它随后更新本地按钮的状态。

问题是,虽然上下文和本地存储的内容似乎都已更新,但项目并未重新呈现。 (当我刷新页面时,我可以看到按钮已经改变了状态,但是,这表明它能够很好地从上下文中获取该信息。

我现在将分享一些代码,希望有人能够理解我可能遗漏的内容,非常感谢您的帮助:)

上下文提供程序设置

type FavoritesContextType = {
  favorites: Favorites;
  updateFavorites: (category: StorageCategory, item: string) => void;
};

export const FavoritesContext = createContext<FavoritesContextType>(
  {} as FavoritesContextType
);

const FavoritesProvider: FC = ({ children }) => {
  const [favorites, setFavorites] = useState<Favorites>(
    getFromLocalStorage(SOME_CONSTANT)
  );

  const updateFavorites = (category: StorageCategory, item: string) => {
    updateLocalStorage(category, item);
    setFavorites(favorites);
  };

  return (
    <FavoritesContext.Provider value={{ favorites, updateFavorites }}>
      {children}
    </FavoritesContext.Provider>
  );
};

export const useFavoritesContext = () => useContext(FavoritesContext);

App.tsx

export const App = () => {
  return (
    <FavoritesProvider>
      {/* Some routing wrapper and a few routes each rendering a component */}
      <Route path="/launches" element={<Launches />} />
    </FavoritesProvider>
  )

Launches.tsx

export const LaunchItem = ({ launch }: LaunchItemProps) => {
  const { favorites, updateFavorites } = useFavoritesContext();
  const [isFavorite, setIsFavorite] = useState(false);

  useEffect(() => {
    if (favorites) {
      setIsFavorite(
        favorites.launches.includes(launch.flight_number.toString())
      );
    }
  }, [favorites]);

  return (
    {/* The rest of the component, irrelevant */}
    <FavoriteButton
      isFavorite={isFavorite}
      updateFavorites={() => {
        updateFavorites(
          StorageCategory.Launches,
          launch.flight_number.toString()
          );
       }}
   />
  )

FavoriteButton.tsx

export const FavoriteButton = ({
  isFavorite,
  updateFavorites,
}: FavoriteButtonProps) => {
  const handleClick = (e: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => {
    e.preventDefault();
    updateFavorites();
  };

  return (
    // Using Link vs a Button to be able to preventDefault of parent Link
    <Link
      onClick={handleClick}
    >
    {/* The rest of the component, irrelevant */}

似乎在您的 updateFavorites 函数中您正在调用 setFavorites 并传入现有的 favorites 值。尝试将 updateFavorites 函数写成:

  const updateFavorites = (category: StorageCategory, item: string) => {
    updateLocalStorage(category, item);
    setFavorites(getFromLocalStorage(SOME_CONSTANT));
  };

还有其他方法可以确定要传递给 setFavorites 的值,但我重复使用了您的 getFromLocalStorage 函数,因为我不确定您是如何确定该状态值的。

通过这种方式,您将确保您在 setFavorites 中设置的值与现有的 favorites 值不同,因此您将触发 re-render.