在渲染时获取redux状态的初始副本,以便在单击按钮后重置它



我有一些按钮在我的导航栏当点击返回过滤状态。这些对象然后被用来在我的UI中渲染卡片。

<div className="filter-buttons">
<button className="filter-btn" onClick={() => setFilter("nature")}>Nature</button>
<button className="filter-btn" onClick={() => setFilter("tech")}>Tech</button>
<button className="filter-btn" onClick={() => setFilter("education")}>Education</button>
</div>

我使用redux工具箱库为我的状态。我拉入所有博客对象并将其存储到一个变量中。我有一个useEffect钩子,每次点击按钮时运行,尝试重置状态并再次过滤所有对象。

const blogsCopy = JSON.stringify(useSelector((state) => state.blog));
const allBlogs = useSelector((state) => state.blog);
const myBlogs = useSelector((state) => state.user.blogs);
const [filter, setFilter] = useState("");
const originalState = useMemo(() => JSON.parse(blogsCopy), []);

useEffect(() => {
setNavFilterLoading(true);
let filteredBlogs = [];
const keys = Object.keys(allBlogs);
if (filter.startsWith("nat")) {
// reset the state to the original state
dispatch(setWholeState(originalState));
console.log("original state", originalState);
filteredBlogs = keys.filter(key => allBlogs[key].tags.some(tag => tag.startsWith("nat"))).map((key, index) => ({index, ...allBlogs[key]})
);
} else if (filter.startsWith("tech")) {
filteredBlogs = keys.filter(key => allBlogs[key].tags.some(tag => tag.startsWith("tech"))).map((key, index) => ({index, ...allBlogs[key]})
);
} else if (filter.startsWith("edu")) {
filteredBlogs = keys.filter(key => allBlogs[key].tags.some(tag => tag.startsWith("edu"))).map((key, index) => ({index, ...allBlogs[key]})
);
} else {
filteredBlogs = keys.map((key, index) => ({index, ...allBlogs[key]})
);
}
dispatch(setWholeState(filteredBlogs));
setNavFilterLoading(false);
}, [filter]);

这个实现的问题是,对象发生了变异,我无法再次重置状态。如果我点击自然按钮,它会返回3个对象。如果其中一个包含"科技"标签。它将过滤三个对象并返回一个对象。我希望它将整个状态重置为初始副本,以正确地过滤掉它。不过滤已过滤的内容

我认为使用useEffectfilteredBlogs保存到存储中可能没有必要,因为filter似乎仅供本地使用。

假设目标是过滤数据以进行条件显示,并且从存储中检索的数据按预期工作,也许不需要更改数据,相反,可以在组件中创建本地filteredBlogs

一个粗略的例子可以是:

const blogsCopy = JSON.stringify(useSelector((state) => state.blog));
const allBlogs = useSelector((state) => state.blog);
const myBlogs = useSelector((state) => state.user.blogs);
const [filter, setFilter] = useState("");
const filteredBlogs = allBlogs.filter((item) =>
filter ? item.tags.some((tag) => tag.startsWith(filter)) : true
);

本地filteredBlogs可以用于filteredBlogs.map()的输出,当filter状态改变时,它将被更新。

也许按钮也可以更改为将较短的值保存为filter,以简化逻辑:

<div className="filter-buttons">
<button className="filter-btn" onClick={() => setFilter("")}>Clear all</button>
<button className="filter-btn" onClick={() => setFilter("nat")}>Nature</button>
<button className="filter-btn" onClick={() => setFilter("tech")}>Tech</button>
<button className="filter-btn" onClick={() => setFilter("edu")}>Education</button>
</div>

最新更新