【问题标题】:useContext is declared at top level but value is not updated in another functionuseContext 在顶层声明,但值未在另一个函数中更新
【发布时间】:2020-03-25 19:18:02
【问题描述】:

我在 myComponent 的顶部使用 useContext 来获取价值。

我有一些公共 API 函数使用它的值。可以在父组件中随时调用和更新 useContext 值。但后来在 myComponent 的另一个函数中仍然采用旧值。

这里不能使用useEffect,因为它是可以随时调用的公共API。

我在下面提供了示例:

在 state/index.js 中,

import React, { createContext, useContext, useReducer } from 'react';
import reducer from 'reducers';
import PropTypes from 'prop-types';

const initialState = {
   test: true,
};

const StateContext = createContext();

const StateProvider = ({ children }) => (
 <StateContext.Provider value={useReducer(reducer, initialState)}>
  {children}
 </StateContext.Provider>
);

const useStateValue = () => useContext(StateContext);

StateProvider.propTypes = {
  children: PropTypes.any,
};

StateProvider.defaultProps = {
 children: {},
};

export { StateContext, StateProvider, useStateValue };

在 main.js 中

<StateProvider>
   <App/>
</StateProvider>

在actions/app.js中

const TEST_FALSE = 'TEST_FALSE';
const TEST_TRUE = 'TEST_TRUE';

const testTrue = dispatch => {
  dispatch({
    type: TEST_TRUE,
  });
};

const testFalse = dispatch => {
    dispatch({
      type: TEST_FALSE,
    });
 };

export {
  TEST_FALSE,
  TEST_TRUE,
  testTrue,
  testFalse,
};

在 reducers/index.js 中

import { TEST_FALSE, TEST_TRUE } from 'actions/App';
import { isEmpty } from 'Utils';

const testReducer = (state, action) => {
  switch (action.type) {
    case TEST_FALSE:
      return {
        ...state,
        test: false,
      };
    case TEST_TRUE:
      return {
        ...state,
        test: true,
      };
    default:
      return state;
  }
};

const rootReducer = ({ test }, action) => ({
  test: testReducer(test, action),
});

export default rootReducer;

在 app.js 中

import { testTrue, testFalse } from 'actions/App';

import { useStateValue } from '../state';

const App = props => {
  const [{ test }, dispatch] = useStateValue();

  const updateTestTrue = () => {
    testTrue(dispatch);
  }

  const updateTestFalse = () => {
    testFalse(dispatch);
  }

  const checkTest = () => {
    console.log('check test', test) // here it always returns initial state value even after value gets updated
  }
  return (<div>test</div>)

}
export default App;

checkTestupdateTestFalseupdateTestTrue 是示例公共 API 函数。稍后使用它,我将被调用并更新该值。组件正确呈现。

但在 checkTest 函数中,它只取初始值为真。不采用更新的值。

例如,如果我通过调用 updateTestFalse 函数进行更新。虽然我调用 checkTest 仍然采用旧值。

请告诉我这里缺少什么?我想在 checkTest 函数中使用更新后的值

【问题讨论】:

  • 您必须create a Minimal, Reproducible Example 才能获得有关您所缺少内容的具体答案。但猜测一下 - 渲染之间的值会发生变化(例如,从事件处理程序或 Promise.then() 内部),因此将使用旧值进行 1 次渲染,使用新值进行第 2 次渲染。您可能正在检查旧渲染中的值......或者您可能正在就地改变一些对象/数组(这不会触发重新渲染)。
  • @Aprillion 我已经编辑了问题。请检查并告诉我
  • 发现问题。实际上我正在 iframe 中加载我的应用程序并尝试将公共事件绑定到 iframe。因此,它不采用“test”的当前值。使用此github.com/donavon/use-event-listener 绑定事件侦听器后,它可以工作。谢谢。

标签: reactjs react-hooks


【解决方案1】:
  1. rootReducer 将返回 {test: false} 用于初始状态,但在 updateTestTrue 之后,它将是 {test: {test: true}}
  2. 你已经定义了checkTest,但从不在问题代码中调用它。如果在渲染同步代码之外调用它,请参阅useState set method not reflecting change immediately 了解更多详情

【讨论】:

    猜你喜欢
    • 2021-01-23
    • 1970-01-01
    • 1970-01-01
    • 2016-03-13
    • 2021-08-23
    • 1970-01-01
    • 2014-08-25
    • 2012-10-28
    • 1970-01-01
    相关资源
    最近更新 更多