1

I'm trying to integrate Redux in a project that works already. I've configured the Redux store using multiple slices, here's the one causing troubles:

const initialCategoriesState = [];

const categoriesSlice = createSlice({
  name: "categories",
  initialState: initialCategoriesState,
  reducers: {
    setCategories(state, action) {
      state = action.payload;   
    },
  },
});

In my component I'm using useSelector to access the state:

const categories = useSelector(state => state.categories);

And to update it I dispatch an action, accordingly with the one declared in the slice:

const fetchedCategories = await fetchData(urlCategories, CATEGORIES);
dispatch(categoriesActions.setCategories(fetchedCategories));

But once I run the code, the categories constant gets never updated. Since I wasn't sure the action was getting the data, I tried to console.log the state inside the reducer it as it follows:

reducers: {
  setCategories(state, action) {
    console.log("state before", state);
    state = action.payload;
    console.log("state after", state);   
  },
},

The state is indeed changing, but not the extracted state in the categories constant.

Is there something I'm missing here?

2 Answers2

1

I've got the same problem a few months ago and solved it this way. But, I may be missing something too.

Please try this for your initial state:

const initialCategoriesState = { categories: [] };

And then in your reducer:

state.categories = action.payload;
Thremulant
  • 566
  • 5
  • 15
1

I've found one of the cool things about Redux Toolkit to be it's Entity Adapters, which can safely initialize your state while providing helper functions for updating your state. They (reasonably) assume that your slice will have collections, and probably a main collection of things with the same name as the slice. createEntityAdapter() allows you to do like:

const categoriesAdapter = createEntityAdapter()

// name the below "initialState" exactly
const initialState = categoriesAdapter.getInitialState({
    // this will, by default, get you an `entities{}` and `ids[]` representing your categories
    // you can add any additional properties you want in state here as well
})

Then, when you are wanting to update state, in your reducer you can do like:

reducers: {
  setCategories(state, action) {
    categoriesReducer.setAll(state, action.payload)
    // this will update both entities{} and ids[] appropriately
  },
},
BryanOfEarth
  • 715
  • 11
  • 26