Search code examples
reactjsreduxreact-reduxredux-toolkitnormalizr

Should every React component have it's own slice, when using createEntityAdapter?


I'm using Redux-tookit's createSlice and createEntityAdapter with normalized data.

This is a typical blog app with (posts, comments, users) - Entities

Usually, before using createEntityAdapter I would:

  1. Fetch, normalize and store data in postsSlice
    So my postSlice state would look something like this:
    blogPosts: {entities: {posts: {}, users:{}, comments: {}}, ids:[]}
  2. Get id's from postsSlice's state to Posts component
  3. Pass comment/user id's from Posts down to children - Comment User components, where they would get data using passed id's with selectors connected to parent's postSlice state
const postsAdapter = createEntityAdapter();

const postsSlice = createSlice({
  name: "posts",
  initialState: postsAdapter.getInitialState(),

  reducers: {
    setPosts: (state, { payload }) =>
      postsAdapter.setAll(state, payload.entities.posts),
  },
});

The problem is:

  • When using createEntityAdapter
    Since we're using createEntityAdapter.getInitialState() we get the same initialState {entities: {} ids: []} pattern in every slice.
  • And this doesn't allow to have initialState like I had before:
    blogPosts: {entities: {posts: {}, users:{}, comments: {}}, ids:[]}

Should every component (Posts, User, Comment) have it's own slice/reducer and fetch it's own piece of data with thunk from the same endpoint?

So that: (according the createEntityAdapter.getInitialState() pattern)

  • postSlice state would just contain post Entity - entities: {posts: {}, ids:[]}
  • commentSlice state - comments Entity - entities: {comments: {}, ids:[]}
  • etc...

Solution

  • No. There has never been a 1:1 association between components and Redux state structure. Instead, you should organize your state in terms of your data types and update logic, and components should access and re-shape that data for their own needs as necessary.

    Note that there are multiple ways to approach structuring that data in the store even if it's being normalized. For example, you could have each data type as its own top-level slice, or have a shared entities reducer with each of those types nested inside.