Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/463.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何使用没有提供程序的上下文更新每个React组件?_Javascript_Reactjs_React Hooks_React Hoc - Fatal编程技术网

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并发布它。。。