Jeremias
Jeremias

Reputation: 433

How can I access state of another slice in redux with redux-toolkit?

In my Redux store I have multiple slices and I would like to access the lang state of the settingsSlice inside the speciesSlice.

Here is a code sample of my slices:

const settingsSlice = createSlice({
  name: 'settings',
  initialState: { lang: 'en', theme: 'dark' },
  reducers: {
    ...
  },
});

const speciesSlice = createSlice({
  name: 'species',
  initialState: data[`vds-list-${HERE I WANT TO USE THE "lang" STATE OF THE SETTINGSSLICE}`],
  reducers: {
    ...
  },
});

Thus far I haven't found a solution so maybe it's just not possible?

I could just use one slice with all of the state inside of there, but I'd really like to separate different parts of the state in different slices.

Upvotes: 43

Views: 55062

Answers (7)

Mustapha GHLISSI
Mustapha GHLISSI

Reputation: 1710

If you're familiar with Redux Thunk then this should be easy. Redux Toolkit integrates by default Thunk configuration which is ready to use.

To make an async call basically you need to pass dispatch, moreover getState is on your hand to retrieve any information from the store state !

For example, I've two slices category and main, and here I need to fetch categories but this depends on main slice state property called isOffline

export const fetchCategories = () => (dispatch, getState) => {
  dispatch(handleLoad(true));
  const {isOffline} = getState().main;

  if (isOffline) {
    setTimeout(async () => {
      const categories = await getDataObject('categories');
      dispatch(fetchCategoriesSuccess(categories ?? []));
      dispatch(handleLoad(false));
    }, 1000);

    return false;
  }
};

Upvotes: 1

Mher
Mher

Reputation: 1

It is not necessary to hard code.
If you want to use a data from X slice in Y slice, all you have to do is export the initial state of X slice and import it in Y slice, so that whenever the X slice state changes, it will automatically change it in Y slice also.

Upvotes: -3

Rustem
Rustem

Reputation: 116

We can do it by adding extraReducers to respond to the action

// Slice A - sliceA.js
export const sliceAinitialState = {
  lang: 'en',
}
const sliceA = createSlice({
  name: 'A'
  initialSlice: sliceAinitialState,
  reducers: {
    langChangedAtSliceA: (state, action) => state.lang = action.payload,
  }
})
export const {langChangedAtSliceA } = sliceA.actions

// Slice B - sliceB.js
import {sliceAinitialState, langChangedAtSliceA} from 'sliceA.js'
const sliceB = createSlice({
  name: 'B'
  initialSlice: {
    lang: sliceAinitialState.lang
  },
  extraReducers: (builder) => {
    builder.addCase(langChangedAtSliceA, (state, action) => {
      state.lang = action.payload
    })
  }
})

Upvotes: 9

challet
challet

Reputation: 972

There is a specific createDraftSafeSelector function available in redux-toolkit for that usage.

Upvotes: 0

Josh Kelley
Josh Kelley

Reputation: 58362

As referenced in the Redux FAQ entry, "How do I share state between two reducers?", you can use redux-thunk to write a reducer that can access the entire state. For example:

const speciesSlice = createSlice({
  name: 'species',
  initialState: data[`vds-list-${HERE I WANT TO USE THE "lang" STATE OF THE SETTINGSSLICE}`],
  reducers: {
    ...
    internalSetLang: (state, action) => {
      state = data[`vds-list-${action.payload}`];
    },
    ...
  },
});

const { internalSetLang } = speciesSlice.actions;

export function setLang() {
  return (dispatch, getState) => {
    const lang = getState().settings.lang;
    dispatch(internalSetLang(lang));
  };
}

This is similar to @Biskrem Muhammad's answer but avoids having to use the Redux store as a global variable.

Upvotes: 7

Muhammad Omran
Muhammad Omran

Reputation: 4615

I've managed to achieve this by simply importing the redux store object and have called getState() method.

so in speciesSlice reducer action you can do that:

const speciesSlice = createSlice({
  name: 'species',
  initialState: data[`vds-list-${HERE I WANT TO USE THE "lang" STATE OF THE SETTINGSSLICE}`],
  reducers: {
    ...
    setLang: (state, _) => {
      const reduxStore = store.getState();
      const lang = reduxStore.settingsSlice.lang;
      state = data[`vds-list-${lang}`];
    },
    ...
  },
});

Upvotes: 11

markerikson
markerikson

Reputation: 67469

Reducers, by definition, only have access to the section of state that they own. So, if I have {users: usersReducer, posts: postsReducer}, the usersReducer has no access to the posts state slice at all.

See the Redux FAQ entry on "how can I share state between reducers?" for more details.

Upvotes: 32

Related Questions