ioof-holdings / redux-dynostore

These libraries provide tools for building dynamic Redux stores.
BSD 3-Clause "New" or "Revised" License
122 stars 15 forks source link

Getting error 'mapState must not return undefined' after calling function store.detachReducers(['dynamicReducer']) #258

Closed as4ashish closed 4 years ago

as4ashish commented 4 years ago

Is it a bug, feature request or question?

Bug

Which package(s) does this involve?

Counter.txt [@redux-dynostore/core]"

Sandbox URL

https://codesandbox.io/s/staging-fire-84m98?file=/src/components/Counter.js

Input Code

// your code here
const {identifier} = props;
onClick={() => {
          rootStore.dispatch({ type: DELETE_COUNTER, value: props.identifier });
          rootStore.detachReducers([props.identifier]);
        }}

Expected Behavior

So this onClick on button 'Remove Counter' dispatch action to remove that counter from allId in allCountersReducer then uses detachReducers with rootStore to delete that dynamic reducer associated with that instance of counter (see counter component in codesanbox )

Current Behavior

Now Its deleted the counter and its dynamic reducer but after that verifyState function runs in library 'node_modules/redux-subspace/lib/index.js:234:11' and return an error like 'TypeError mapState must not return undefined.' I'm doing as stated in docs to remove any dynamic reducer 'https://github.com/ioof-holdings/redux-dynostore/tree/master/packages/redux-dynostore-core' still getting this error, unable to figure out what is wrong with this approach or this function is not implemented correctly

Possible Solution

If I remove this line rootStore.detachReducers([props.identifier]); the code works perfect but instance of its reducer is still in rootStore, so I want to delete its reducer instance once that instance of counter is deleted. so I'm using detachReducers(), but causing error

Context

Your Setup

package version(s)
redux 4.0.5
redux-dynostore 3.1.0
react 16.13.1
mpeyper commented 4 years ago

This is a timing issue more than a bug. You cannot remove a reducer that is being used by a component that is still mounted, and calling detachReducers in the click handler is going to remove the reducer before the the component has unmounted and unfortunately there is an additional render that kicks in because of it.

The simplest approach is to move the call to either componentWillUnmount or the the cleanup of a useEffect (like I did in your example).