在不改变全局状态的情况下过滤组件中的 useContext 状态
Filter useContext state in a component without changing global state
我有一个使用 useContext
检索全局状态的组件,它是 movies/TV 节目的列表。我试图将这个全局状态保存到本地状态,这样我就可以在单击按钮时按媒体类型(电影或电视节目)过滤列表,但过滤器应该只反映在本地,而不是调度一个动作来改变全局状态(我不想丢失完整的列表)。
但是,将全局状态存储到局部状态后,局部状态为空。这是组件的代码:
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;
我不明白为什么这不起作用。任何帮助将不胜感激!
您不能像 (const [watchList, setWatchList] = useState(state);
) 那样直接将 global state
与 local state
联系起来:-
通过这样做,它会自动与你在 context
中声明的 state
的 default
值联系起来,它总是一个 空 array
或 []
。所以要解决这个问题,你为什么不 track
将 state
的传入 更改 与 useEffect
,像这样:-
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;
我有一个使用 useContext
检索全局状态的组件,它是 movies/TV 节目的列表。我试图将这个全局状态保存到本地状态,这样我就可以在单击按钮时按媒体类型(电影或电视节目)过滤列表,但过滤器应该只反映在本地,而不是调度一个动作来改变全局状态(我不想丢失完整的列表)。
但是,将全局状态存储到局部状态后,局部状态为空。这是组件的代码:
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;
我不明白为什么这不起作用。任何帮助将不胜感激!
您不能像 (const [watchList, setWatchList] = useState(state);
) 那样直接将 global state
与 local state
联系起来:-
通过这样做,它会自动与你在
context
中声明的state
的default
值联系起来,它总是一个 空array
或[]
。所以要解决这个问题,你为什么不track
将state
的传入 更改 与useEffect
,像这样:-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;