ReactJs 上下文未更新,值始终为默认值

Posted

技术标签:

【中文标题】ReactJs 上下文未更新,值始终为默认值【英文标题】:ReactJs Context not updated, values always default 【发布时间】:2021-11-23 10:45:02 【问题描述】: 我有父包装组件,我在里面添加了react context。 在该包装器组件中,我还有 useEffect() 挂钩,用于从 API 获取一些值,然后将这些值设置为上下文。 在使用上下文的子组件中上下文的值始终是默认值。当我签入浏览器反应工具时,似乎上下文的值已更新,但当我使用 console.log 对其进行测试时,它总是返回默认值。

内部有上下文的父组件:

...
export const CorporateContext = createContext(corporateId: null, corporateRole: null, corporateAdmin: null, corporateSuperAdmin: null);

export const CorporateWrapper = ( apiBaseUrl, children ) => 
    const [corporateContextDefaults, setCorporateContextDefaults] = 
    useState(corporateId: null, corporateRole: null, corporateAdmin: null, corporateSuperAdmin: null);

    useEffect(() => 
        (async () => 
            try 
                const json = await fetchCorporateUserDetails(apiBaseUrl);

                if (json.success !== true) 
                    console.log(json.message);
                   else 
                    console.log(json.data) // <-- TESTED RESPONSE FROM API
                    setCorporateContextDefaults(json.data); // <-- UPDATE CONTEXT VALUES HOOK AND PASS IT BELOW TO CONTEXT PROVIDER
                  

               
                 catch (e) 
                    console.log(e.message);
                
            )();
    , []);

    return (
        <CorporateContext.Provider value=corporateContextDefaults>
        children
        </CorporateContext.Provider>
    );
;

export default CorporateWrapper;

正在使用该上下文的子组件:

const CorporateSettingsPage: React.FC<CorporateSettingsPageProps> = (
  apiBaseUrl,
  campusBaseUrl,
  ecomBaseUrl,
: CorporateSettingsPageProps) => 
  const corporateContext = useContext(CorporateContext);

  console.log('corporate context is:');    //<-- ALWAYS RETURNS DEFAULT VALUES
  console.log(corporateContext);


  useEffect(() => 
    (async () => 
      try 
        const json = await fetchCorporateSettings(apiBaseUrl, 
corporateContext.corporateId);
  ...
    )();
  , [corporateContext]);

  return (
      <CorporateWrapper apiBaseUrl=apiBaseUrl> // <--- PARENT COMPONENT WITH CONTEXT INSIDE
        <div>
           ...
           <SomeOtherComponent />   // <-- CONTEXT IS CORRECT HERE AND UPDATED VALUES ARE SHOWN
        </div>
      </CorporateWrapper>
  );

【问题讨论】:

尝试在每次更改时记录corporateContextDefaults 的父组件中添加一个useEffect 挂钩。通过这种方式,我们排除了问题不在状态而是在上下文中。如果它没有记录任何内容或在上次更新中记录了默认值,则问题处于状态 我试过了。第一个 console.log 是默认值,然后第二个是来自 api 的值,非常正确。我更新了我的问题。还有一个子组件在其中具有正确的上下文值,因此上下文在那里可以正常工作。也许我的整个“子组件”实际上并不是一个子组件,因为在该页面内我将页面内容包装在包装器组件中 如果您在非孩子中使用您的上下文,那么您发现了您的问题。由于您的组件不会是您定义的提供者的子组件,因此它永远不会收到您的值 现在,当我在 app.js 文件中添加该包装器并将其从上面的文件中删除时,它工作正常。将所有内容都包含在 app.js 中是正确的地方吗? 上下文可以放在任何地方,重要的是你尊重消费者是组件的孩子这一事实。显然,将每个上下文放入 app.js 中很快就会变得难以维护,因此请始终尝试“这是正确的位置吗?”。也许你会注意到创建另一个组件是必要的 【参考方案1】:

尝试做这些事情:

    首先确保状态正确更新。这应该足以调试:
useEffect(()=>
console.log(corporateContextDefaults);
,[corporateContextDefaults])
    如果状态更新正确,则问题出在您的 Provider->Consumer 关系中。

验证您的消费者是提供组件的子组件。

【讨论】:

是的,就是这样 -> 如果状态正确更新,则问题出在您的 Provider->Consumer 关系中。错误的关系 @Denis2310 我只是为将来可能会阅读的未来读者指出一个可能的程序,现在我将在上面回答

以上是关于ReactJs 上下文未更新,值始终为默认值的主要内容,如果未能解决你的问题,请参考以下文章

java-int类型:int默认为0导致更新操作未赋值的情况下将值更新为0

从 DropdownItems 中选择值后,DropdownButton 值未更新。如何使用 selectedValue 更新默认值?

如何将 fetch() 函数的结果传递给 React 上下文值,而不是我为钩子设置的默认值?

未初始化的 int 值始终相同 (C++)

如何将默认反应上下文值设置为来自 Firestore 的数据?

调用 setState 后 ReactJS 元素未更新