[英]cant update context state when using hooks with a complex object to set providers value
When I call toggleFilterSidebar
it should toggle the state of filterSidebarIsOpen from false to true and vice versa but onClick nothing happens, but when I pass the Provider value directly as an object it works. 当我调用toggleFilterSidebar
,应该将toggleFilterSidebar
的状态从false切换为true,反之亦然,但是onClick不会发生任何事情,但是当我直接将Provider值作为对象传递时,它就可以工作。
Why does this work? 为什么这样做?
1). 1)。
return <FilterSidebarContext.Provider value={{
toggleFilterSidebar,
filterSidebarIsOpen,
filters,
}}>{children}</FilterSidebarContext.Provider>;
and this doesnt 而且这不
2). 2)。
const [value] = useState({
toggleFilterSidebar,
filterSidebarIsOpen,
filters,
});
return <FilterSidebarContext.Provider value={value}>{children}</FilterSidebarContext.Provider>;
My Code 我的密码
FilterSidebar.context.js FilterSidebar.context.js
import React, { useState } from 'react';
export const FilterSidebarContext = React.createContext({});
export const FilterSidebarProvider = ({ children }) => {
const [filterSidebarIsOpen, setFilterSidebarIsOpen] = useState(true);
const toggleFilterSidebar = () => setFilterSidebarIsOpen(!filterSidebarIsOpen);
const [filters] = useState({ regions: [] });
const [value] = useState({
toggleFilterSidebar,
filterSidebarIsOpen,
filters,
});
return <FilterSidebarContext.Provider value={value}>{children}</FilterSidebarContext.Provider>;
};
export const FilterSidebarConsumer = FilterSidebarContext.Consumer;
export default FilterSidebarContext;
FilterButton.js FilterButton.js
const FilterButton = ({ className, getTotalActiveFilters }) => {
const { toggleFilterSidebar, filterSidebarIsOpen } = useContext(FilterSidebarContext);
return <Button className={cx({ [active]: filterSidebarIsOpen })} onClick={toggleFilterSidebar} />;
};
With this code: 使用此代码:
const [value] = useState({
toggleFilterSidebar,
filterSidebarIsOpen,
filters,
});
you are providing useState
with an initial value which is only used when the component is first mounted. 您正在为useState
提供一个初始值,该初始值仅在首次安装组件时使用。 It will not be possible for value
to ever change since you aren't even creating a variable for the setter (eg const [value, setValue] = useState(...)
). 因为您甚至都没有为setter创建变量(例如const [value, setValue] = useState(...)
) const [value, setValue] = useState(...)
所以value
永远都不可能改变。
I assume you are using useState
here to try to avoid a new object being created with each render and thus forcing a re-render of everything dependent on the context even if it didn't change. 我假设您在这里使用useState
来尝试避免在每个渲染过程中创建一个新对象,从而迫使重新渲染依赖于上下文的所有内容,即使它没有更改也是如此。 The appropriate hook to use for this purpose is useMemo
: 用于此目的的合适钩子是useMemo
:
const value = useMemo(()=>({
toggleFilterSidebar,
filterSidebarIsOpen,
filters
})[filterSidebarIsOpen]);
I've only put filterSidebarIsOpen
into the dependencies array, because with your current code it is the only one of the three that can change ( toggleFilterSidebar
is a state setter which won't change, filters
doesn't currently have a setter so it can't change). 我只将filterSidebarIsOpen
放入依赖项数组,因为使用您当前的代码,它是可以更改的三个中的唯一一个( toggleFilterSidebar
是不会更改的状态设置器, filters
当前没有设置器,因此它可以不变)。
useState expects a function to set the value after useState initially does, so if value represents state, setValue would represent setState... useState希望函数在useState最初设置之后设置值,因此如果value表示状态,则setValue表示setState ...
const [value, setValue] = useState(initialValue);
then use setValue to change it 然后使用setValue进行更改
onClick={() => setValue(newValue)}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.