首页 > 解决方案 > 过滤组件中的 useContext 状态而不更改全局状态

问题描述

我有一个useContext用于检索全局状态的组件,它是电影/电视节目的列表。我正在尝试将此全局状态保存到本地状态,以便在单击按钮时按媒体类型(电影或电视节目)过滤列表,但过滤器应仅在本地反映,而无需调度操作来更改全局状态(我不希望丢失完整的列表)。

但是,将全局状态存储到本地状态后,本地状态为空。这是组件的代码:

import React, { useContext, useState, useEffect } from "react";

import { WatchListContext } from "../../contexts/WatchListProvider";

import WatchItem from "../WatchItem";

const WatchList = () => {
  const { state } = useContext(WatchListContext);
  const [watchList, setWatchList] = useState(state);
  const [filter, setFilter] = useState("");

  useEffect(() => {
    setWatchList((previousWatchlist) => {
      const filteredWatchList = previousWatchlist.filter(
        (watchItem) => watchItem.media_type === filter
      );

      return filteredWatchList;
    });
  }, [filter]);

  return (
    <div>
      <div>
        <button onClick={() => setFilter("tv")}>TV</button>
        <button onClick={() => setFilter("movie")}>MOVIES</button>
      </div>

      {watchList
        .filter((watchItem) => watchItem.media_type === filter)
        .map(({ id, title, overview, poster_url, release_date, genres }) => (
          <WatchItem
            key={id}
            title={title}
            overview={overview}
            poster_url={poster_url}
            release_date={release_date}
            genres={genres}
          />
        ))}
    </div>
  );
};

export default WatchList;

我不明白为什么这不起作用。任何帮助都感激不尽!

标签: reactjsuse-statestate-managementreact-state-managementreact-context

解决方案


你不能像你做的那样直接把你global state和你local state喜欢的人联系起来(const [watchList, setWatchList] = useState(state);):-

  • 通过这样做,它将自动与您声明的default值联系起来,其中始终为或。所以要解决这个问题,为什么不使用 with的传入更改,如下所示:-statecontext array[]trackstateuseEffect

  • WatchList.js:-

import React, { useContext, useState, useEffect } from "react";

import { WatchListContext } from "../../contexts/WatchListProvider";

import WatchItem from "../WatchItem";

const WatchList = () => {
  const { state } = useContext(WatchListContext);
  const [watchList, setWatchList] = useState([]);
  const [filter, setFilter] = useState("");

  // handle fetching current changes of state received by Context
  useEffect(() => {
    (() => setWatchList(state))()
  }, [state])  

  // handle filtering of data
  useEffect(() => {
    setWatchList((previousWatchlist) => {
      const filteredWatchList = previousWatchlist.filter(
        (watchItem) => watchItem.media_type === filter
      );

      return filteredWatchList;
    });
  }, [filter]);

  return (
    <div>
      <div>
        <button onClick={() => setFilter("tv")}>TV</button>
        <button onClick={() => setFilter("movie")}>MOVIES</button>
      </div>

      {watchList
        .filter((watchItem) => watchItem.media_type === filter)
        .map(({ id, title, overview, poster_url, release_date, genres }) => (
          <WatchItem
            key={id}
            title={title}
            overview={overview}
            poster_url={poster_url}
            release_date={release_date}
            genres={genres}
          />
        ))}
    </div>
  );
};

export default WatchList;

推荐阅读