Javascript 如何使用没有提供程序的上下文更新每个React组件?
给出了这个简单的定制钩子Javascript 如何使用没有提供程序的上下文更新每个React组件?,javascript,reactjs,react-hooks,react-hoc,Javascript,Reactjs,React Hooks,React Hoc,给出了这个简单的定制钩子 import React, { createContext, useContext } from 'react'; const context = { __prefs: JSON.parse(localStorage.getItem('localPreferences') || null) || {} , get(key, defaultValue = null) { return this.__prefs[key] || defaultVa
import React, { createContext, useContext } from 'react';
const context = {
__prefs: JSON.parse(localStorage.getItem('localPreferences') || null) || {} ,
get(key, defaultValue = null) {
return this.__prefs[key] || defaultValue;
},
set(key, value) {
this.__prefs[key] = value;
localStorage.setItem('localPreferences', JSON.stringify(this.__prefs))
}
};
const LocalPreferenceContext = createContext(context);
export const useLocalPreferences = () => useContext(LocalPreferenceContext);
export const withLocalPreferences = Component => () => <Component localPreferences={ useLocalPreferences() } />;
import React,{createContext,useContext}来自“React”;
常量上下文={
__prefs:JSON.parse(localStorage.getItem('localPreferences')||null)|{},
get(key,defaultValue=null){
返回此值。uu prefs[key]| | defaultValue;
},
设置(键、值){
此参数为.\u prefs[key]=值;
localStorage.setItem('localPreferences',JSON.stringify(this.\uu prefs))
}
};
const LocalPreferenceContext=createContext(context);
export const useLocalPreferences=()=>useContext(LocalPreferenceContext);
export const with localpreferences=Component=>()=>;
当我使用这两种方法之一时,在上下文中调用set
不会更新任何内容。当然,React怎么知道我更新了什么?但是可以做些什么来让它工作(不包括使用提供者)
**编辑**
好的,那么除了使用
useContext
之外还有什么选择呢?这才是真正的问题,真的;如何使用这个钩子(或HOC)更新组件?useState
是唯一的方法吗?怎么用?使用一些事件发射器?我认为在这里使用上下文是有意义的,但是您需要使用提供者,因为这是上下文工作方式的核心部分。渲染提供程序使一个值可用于树下更远的组件,而使用新值进行渲染则会提示使用者重新渲染。如果没有提供程序,那么您至少可以访问默认值(这是您在代码中拥有的),但默认值永远不会更改,因此react不会通知消费者
因此,我的建议是添加一个组件,其中包含一个管理与本地存储交互的提供程序。比如:
const LocalPreferenceProvider = () => {
const [prefs, setPrefs] = useState(
() => JSON.parse(localStorage.getItem("localPreferences") || null) || {}
);
// Memoized so that it we don't create a new object every time that
// LocalPreferenceProvider renders, which would cause consumers to
// rerender too.
const providedValue = useMemo(() => {
return {
get(key, defaultValue = null) {
return prefs[key] || defaultValue;
},
set(key, value) {
setPrefs((prev) => {
const newPrefs = {
...prev,
[key]: value,
};
localStorage.setItem("localPreferences", JSON.stringify(newPrefs));
return newPrefs;
});
},
};
}, [prefs]);
return (
<LocalPreferenceContext.Provider value={providedValue}>
{children}
</LocalPreferenceContext.Provider>
);
};
如果您不想自己实现发布/订阅库,或者如果这将成为一个项目的一部分,您可以使用现有的全局状态管理库,如Redux或MobX,我认为在这里使用上下文是有意义的,但您需要使用提供者,因为这是上下文工作的核心部分。渲染提供程序使一个值可用于树下更远的组件,而使用新值进行渲染则会提示使用者重新渲染。如果没有提供程序,那么您至少可以访问默认值(这是您在代码中拥有的),但默认值永远不会更改,因此react不会通知消费者 因此,我的建议是添加一个组件,其中包含一个管理与本地存储交互的提供程序。比如:
const LocalPreferenceProvider = () => {
const [prefs, setPrefs] = useState(
() => JSON.parse(localStorage.getItem("localPreferences") || null) || {}
);
// Memoized so that it we don't create a new object every time that
// LocalPreferenceProvider renders, which would cause consumers to
// rerender too.
const providedValue = useMemo(() => {
return {
get(key, defaultValue = null) {
return prefs[key] || defaultValue;
},
set(key, value) {
setPrefs((prev) => {
const newPrefs = {
...prev,
[key]: value,
};
localStorage.setItem("localPreferences", JSON.stringify(newPrefs));
return newPrefs;
});
},
};
}, [prefs]);
return (
<LocalPreferenceContext.Provider value={providedValue}>
{children}
</LocalPreferenceContext.Provider>
);
};
如果您不想自己实现发布/订阅库,或者如果这将成为一个项目的一部分,您可以使用现有的全局状态管理库,如Redux或MobX,为什么不想使用提供者?如果不需要提供程序,则上下文可能不是要使用的正确工具。如果要更新组件,只需将其与
useState
混合使用即可。如果要使用上下文,则必须有提供程序。这是没有办法的。从外观上看,您所做的只是从localStorage获取和设置项,如果是这样的话,您可以使用useState钩子?您需要一段集中的代码,在启动时从本地存储加载一个值,然后您可以从应用程序中的任何组件对其进行更改。这些更改被推送到本地存储,并触发正在使用该值重新加载的组件。@NicholasTower yup。差不多。你为什么不想使用提供商?如果不需要提供程序,则上下文可能不是要使用的正确工具。如果要更新组件,只需将其与useState
混合使用即可。如果要使用上下文,则必须有提供程序。这是没有办法的。从外观上看,您所做的只是从localStorage获取和设置项,如果是这样的话,您可以使用useState钩子?您需要一段集中的代码,在启动时从本地存储加载一个值,然后您可以从应用程序中的任何组件对其进行更改。这些更改被推送到本地存储,并触发正在使用该值重新加载的组件。@NicholasTower yup。差不多。在函数道具的解构中缺少子类
。正如您所建议的,我最终编写了一个所有提供者
组件,将我的提供者阶梯放在里面。我想我可以重构并合并一些,但我鼓吹契约架构的分离:)也许我应该编写一个useGlobalState
hook并发布它…在函数props解构中缺少children
…我最终编写了一个AllProviders
组件,正如您所建议的,把我的楼梯放进地狱里。我想我可以重构并合并一些,但我鼓吹契约架构的分离:)也许我应该编写一个useGlobalState
hook并发布它。。。