0

I am taking value using useContext at the top in myComponent.

I have a few numbers of public API function which uses its value. It can be invoked and updated useContext value any time in parent component. but later in another function of myComponent still takes old value.

I can’t use useEffect here because it is public API which can be invoked at any time.

I have provided example below:

In 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 };

And in main.js

<StateProvider>
   <App/>
</StateProvider>

And In 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,
};

in 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;

And In 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;

checkTest, updateTestFalse, updateTestTrue are sample public API functions. later using it, I will be invoked and updated the value. Component renders correctly.

But in checkTest functions, it takes only initial value as true. not taking updated value.

For example If I update by invoking updateTestFalse function. While I invoke checkTest still takes old value.

Please let me know what am missing here? I want to use the updated value in checkTest function

Divya
  • 357
  • 1
  • 3
  • 13
  • 2
    You will have to [create a Minimal, Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example) to get a concrete answer about what you are missing. But at a guess - the value is changed between renders (e.g. from an event handler or inside a `Promise.then()`), so there will be 1 render using the old value, and 2nd render using the new value. You might be checking the value from the old render... Or you might be mutating some object/array in-place (which does NOT trigger re-render). – Aprillion Nov 30 '19 at 15:29
  • @Aprillion I have edited questions. Please check and let me know – Divya Dec 03 '19 at 15:03
  • 1
    Found the issue. Actually i was loading my app in iframe and trying to bind public event to iframe. So it is not taking current value for '**test**'. After binding event listener using this https://github.com/donavon/use-event-listener it works. Thanks. – Divya Dec 09 '19 at 12:48

1 Answers1

0
  1. rootReducer will return {test: false} for initialState, but after updateTestTrue, it will be {test: {test: true}}
  2. you have defined checkTest, but never call it in the question code. if it's called outside of render synchronous code, see useState set method not reflecting change immediately for more details
Aprillion
  • 21,510
  • 5
  • 55
  • 89