Harry
Harry

Reputation: 97

Redux state reverting to inital state when navigating backwards React Navigation

not sure if this expected behaviour but I'm trying to persist state between page navigation's using React Navigation, React Native and Redux Toolkit.

So I have a full-screen horizontal scroll list with one element visible at a time, to keep track of what page is visible I am tracking the active index of the element in the view/array.

So I have my state:

type State = {
   pages: Array<{ id, title, name }>,
   activeIndex: number
}

And each time the user scrolls the list I get the index of the new item visible and update the state.

// page slice
const initialState: State = {
    pages: undefined; // async call populates
    activeIndex: 0;
}
const PageListSlice = createSlice({
    name: 'State',
    initialState,
    reducers: {
        setActivePage(
            state: State,
            action: PayloadAction<{ index: number }>,
        ) {
            state.activeIndex = action.payload.index;
            return state;
        },
    }
});

export const setActiveIndex = (activeIndex: number): AppThunk => async (
    dispatch: AppDispatch,
) => {
    dispatch(setLearnState({index: activeIndex}));
};

And loading the state on component mount:

export const ListPage: React.FC<Props> = ({ navigation }): JSX.Element => {
    const dispatch: Dispatch<any> = useDispatch();
    const pageListSlice: State = useSelector((state: RootState) => state.PageState);

    useFocusEffect(
        React.useCallback(() => {
            console.log(pageListSlice.activeIndex); // always returns initial value of 0
        }, []),
    );

    return (
        // ...
    );
}

Now the problem is when I navigate back to that page using React Navigation, the existing state gets replaced by the initial state. This is confusing as the existing state is still present on the screen. What I mean by that is; I will navigate back to the correct item in the list (where I was before), but the state will be incorrect. The state is back to the initial state, so even if I'm looking at the screen found at index 7, the state coming from Redux is the initial value 0.

Is this expected behaviour? Seems crazy to me to have to store state in the cache to persist it between page navigations.

I have loaded the state in children components and the correct state is present so it only seems to be reverting to the initial state when you navigate back a page. I have tried loading the state/adding a new reducer to fire using useFocusEffect but that too returns the initial state.

I've tried to simplify this as much as possible to isolate the issue I'm facing. I hope this makes sense. All help is welcome, thank you.

Versions:

"@react-navigation/bottom-tabs": "^5.2.5",
"@react-navigation/native": "^5.1.4",
"@react-navigation/stack": "^5.2.9",
"@reduxjs/toolkit": "^1.4.0",
"expo": "^37.0.3",
"react": "16.13.1",
"react-native": "https://github.com/expo/react-native/archive/sdk-37.0.0.tar.gz",
"react-redux": "^7.2.0",
"redux-thunk": "^2.3.0"

Upvotes: 0

Views: 852

Answers (1)

satya164
satya164

Reputation: 10145

Your log is incorrect because you have passed an empty dependency array to React.useCallback, which means, the callback never updates to get the correct values.

If you pass proper dependency array to React.useCallback (pageListSlice.activeIndex in this case), then it'll log correct value:

useFocusEffect(
  React.useCallback(() => {
    console.log(pageListSlice.activeIndex);
  }, [pageListSlice.activeIndex])
)

You should use https://www.npmjs.com/package/eslint-plugin-react-hooks plugin to catch such mistakes.

Upvotes: 2

Related Questions