skip to Main Content

I have a React Native app (using TypeScript and Redux-Toolkit (RTK) Query) in which I want to show an intro slider only for the first app launch and never show it again unless the app data is cleared. I have created a slice for its visibility state and am using redux-persist to keep the data.

Upon logout I’m reseting the store and persisted state by following Dan Abramov‘s and Lenz Weber-Tronic‘s recommendations.

// Root reducer (resettable)
const rootReducer = (
  state: ReturnType<typeof appReducer> | undefined,
  action: AnyAction
) => {
  // If the `logout` action is dispatched, clean the `Redux Persist` storage and reset the state
  if (action.type === "auth/logout") {
    storage.removeItem("persist:root");

    return appReducer(undefined, action);
  }

  return appReducer(state, action);
};

I also have separated the persistence config of my intro slice so that I can keep it into storage.

// Root persistence config
const rootPersistConfig = {
  key: "root",
  version: 1,
  storage,
  blacklist: ["intro", api.reducerPath],
};

// Intro slides persistence config
const introPersistConfig = {
  key: "intro",
  version: 1,
  storage,
  blacklist: [api.reducerPath],
};
    
// Top-level reducers
const appReducer = combineReducers({
  [api.reducerPath]: api.reducer,
  auth: authSliceReducer,
  intro: persistReducer(introPersistConfig, introSliceReducer),
});

And this is the intro slice:

interface IntroSliceState {
  /** Whether to show the app intro slides or not */
  showIntro: boolean;
}

const initialState: IntroSliceState = {
  showIntro: true,
};

const introSlice = createSlice({
  name: "intro",
  initialState,
  reducers: {
    hideIntro: (state) => {
      state.showIntro = false;
    },
  },
});

The problem I’m trying to solve now is to find a way to keep the intro slice from being cleared on logout and I know I have to modify this part: return appReducer(undefined, action); but I have no idea how to do it.

2

Answers


  1. Have you tried clearing specific persistors?

    storage.removeItem("persist:intro");
    

    EDIT: Sorry just saw the blacklist. You should still try to single it out to rule out other possibilities

    But I would probably recommend using a local storage for saving first time launch. There used to be AsyncStorage for react native but here are alternatives:

    https://reactnative.directory/?search=storage

    If you use expo, you could use:

    @react-native-async-storage/async-storage

    If you need an example of a first time launch hook + async storage helpers setup send a reply!

    Login or Signup to reply.
  2. Instead of passing undefined state to the reducer so the entire state tree is recomputed from initial state, compute a new state object with only what you want to keep retained.

    Example:

    // Root reducer (resettable)
    const rootReducer = (
      state: ReturnType<typeof appReducer> | undefined,
      action: AnyAction
    ) => {
      // If the `logout` action is dispatched, clean the `Redux Persist`
      // storage and reset the state
      if (action.type === "auth/logout") {
        storage.removeItem("persist:root"); // *
    
        // Keep intro state from previous state
        const { intro } = state;
        // Create new state with retain previous state values
        const nextState = {
          intro,
        };
    
        return appReducer(nextState, action);
      }
    
      return appReducer(state, action);
    };
    

    *Note: storage.removeItem("persist:root"); is one way to delete the persisted state. Another is the persistor.purge method to "clear out the stored state".

    Note also that there may actually be no need to manually clear/purge the storage since upon logout and subsequent state update, the new state will be immediately persisted back out to storage.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search