2

I have a form, which has to be pre-populated with some value. These values come from context. I am using a reducer to handle the state of the form, so I set the initial state of the reducer from what I get from the context. Now what is happening is the context changes but the reducer state doesn't change.

const { selectedCurrency } =
        useContext<CurrenciesContextType>(CurrenciesContext);

const [state, dispatch]: [CurrencyReducerState, Dispatch<any>] = useReducer(
    currencyReducer as ReducerWithoutAction<CurrencyReducerState>,
    selectedCurrency,
    init
);

Ideally, whenever the selectedCurrency changes, it should set the initial values. But it doesn't happen. Any idea why?. I have wrapped the parent component inside the provider. Also every time the selectedCurrency changes, I see the selectedCurrency changing but the reducer state doesn't change. If the component is re-rendered then the reducer picks up the changes and initializes correctly. Is there a way to achieve this?

skyboyer
  • 22,209
  • 7
  • 57
  • 64
Megha bagri
  • 74
  • 2
  • 11
  • The third param init is a function, where is that function defined ? init is termed as Lazy initialization, i am not able to find the snippet from question posted – Learner Jun 19 '21 at 19:22
  • 1
    @Learner `const init = (state)=>({...INITIAL_STATE, ...state});` – Megha bagri Jun 20 '21 at 08:39

2 Answers2

1

I was able to achieve this behaviour by adding a updateState action in my reducer and wrapping this action inside useEffect with selectedCurrency as its dependency :

useEffect(() => {
    actions.updateState(selectedCurrency)
}, [selectedCurrency])

here is what the action looks like :

updateState: (updatedState): void => 
    dispatch({type: "update", payload: updatedState})

The init() function is executed only once when the useReducer is first called.

Similar question - Updating useReducer 'state' using useEffect

Megha bagri
  • 74
  • 2
  • 11
0

Without more example code, it's hard to tell, but maybe you're forgetting to wrap your code with the context provider? The code that needs to use the context (objects and/or callbacks) needs to be wrapped in the provider.

return (
  <div className="App">
    {/* CurrenciesProvider enables children to use the context info */ } 
    <CurrenciesProvider>
      <CurrencySelector />
      <CurrencyDisplay />
    </CurrenciesProvider>
  </div>
);

Here's a codesandbox... https://codesandbox.io/s/kind-noether-zr9dq

Chris Farmer
  • 24,974
  • 34
  • 121
  • 164
  • I have wrapped the parent component inside the provider. Also every time the selectedCurrency changes, I see the selectedCurrency changing but the reducer state doesn't change. If the component is re-rendered then the reducer picks up the changes and initializes correctly. – Megha bagri Jun 20 '21 at 08:38
  • Then post a codesandbox demoing the problem. It’ll be easier to help fix if you show an example where it fails. – Chris Farmer Jun 20 '21 at 12:39
  • Basically, I want to reinitialize my reducer's initial state whenever there's a change in the context variable. is it possible? – Megha bagri Jun 20 '21 at 13:34