Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Duplicating state in Redux

Let's say you have a book application using Redux with a few features:

  • Buy books
  • Have a wishlist of books
  • Maintain a list of books you own
  • Send recommendations to friends
  • Review books

Now let's say that all of these different modules, and a common feature across all these modules is the ability to search for books (i.e. searching for books to buy, books to add to a wishlist, books to review, etc).

These search results will be stored across multiple slices of the state tree.

An example of the state tree might look like this:

{
  bookStore: {
    booksSearchResults: [],
    ...,
  },
  wishlist: {
    booksSearchResults: [],
    ...,
  },
  reviews: {
    newReview: {
      booksSearchResults: [],
      ...,
    },
    ...
  },
  ...
}

Are there any best practices around managing such things? Would it be simply to have a booksSearch slice of state and manage that through a shared component?

How about cases where you might need to search for books in multiple places on the same screen (i.e. you might have an autocomplete search feature in the nav bar in addition to a search component in the main part of the application)?

Is another approach to reuse the search logic and somehow have it update different parts of the state (and if so, does something exist to achieve this)?

like image 662
NRaf Avatar asked Jan 23 '18 03:01

NRaf


People also ask

How do you persist state in Redux?

For that, Redux Persist includes the PersistGate component. To use PersistGate , go to the index. js file in the src directory and add the following import: // src/index.

Can we change Redux state directly?

Redux restricts updating the state to this method only. This strict way of updating the state ensures that the state can not be changed directly either by view or any network callback. The only way to update a state is by defining the action and then dispatching it. Remember that actions are plain JavaScript objects.

Where does Redux keep the state?

The way Redux works is simple. There is a central store that holds the entire state of the application. Each component can access the stored state without having to send down props from one component to another. There are three core components in Redux — actions, store, and reducers.

Why is state read only in Redux?

As mentioned above, state in Redux is read-only. This helps you restrict any part of the view or any network calls to write/update the state directly. Instead, if anyone wants to change the state of the application, then they'll need to express their intention of doing so by emitting or dispatching an action.


1 Answers

I have two pieces of advice for you:

  1. Normalize your store.
  2. Don't store your search results in redux.

Normalization

This is well documented, so I won't go too deep into it here. Suffice it to say that normalizing your store will be flexible and help you to reason about your app. Think of your store as you would a server-side database and it will be more reusable than if you were to tailor each section of the state to your views.

One way you could do this for your app:

{
  books: { 
    bookId: { 
      bookDetails,
      reviews: [ reviewId ],
      ownedBy: [ userId ],
      wishlistedBy: [ userId ],
      recommendations: [ recommendationId ]
    }
  },
  users: {
    userId: { 
      userDetails,
      reviews: [ reviewId ],
      wishlist: [ bookId ],
      ownedBooks: [ bookId ],
      friends: [ userId ],
      sentRecommendations: [ recommendationId ],
      receivedRecommendations: [ recommendationId ]
    }
  },
  reviews: {
    reviewId: {
      bookId,
      userId,
      reviewDetails
    }
  },
  recommendations: {
    recommendationId: {
      sender: userId,
      recipient: userId,
      bookId,
      recommendationDetails
    }
  }
}

You may not need all of those relationships, so don't feel like you have to implement all of that. But starting with a base similar to this will make it much easier to add features later.

Resources:

  • Normalizing State Shape
  • Why normalize?

Where to put search results

Search results are more of a view detail than a data concern. You may need to store a historical record of searches, and in that case, you could add a reducer for searches:

{
  searches: [
    {
      searchTerm,
      searchDetails
    }
  ]
}

But even in that case, I don't think I would store the search results. Storing results will limit functionality in a couple cases.

  1. When the user searches, then a new book is added, you wouldn't find the new book on a subsequent search unless you re-run the search (which negates the usefulness of storing results).
  2. Searching needs to be quick and storing results only speeds up repeated searches (which will likely be less common).

So, I consider results a view detail--or, as James K. Nelson calls it, "Control State" (read: The 5 Types of React Application State). Your question doesn't say which view library (if any) you're using, but the concepts here should be applicable regardless of whether you're using React or not.

Search results should be calculated by the view. The view will receive user input, potentially fetch data (which will be added to the store), run some filter function on the Redux state, and display the results.

like image 66
Luke Willis Avatar answered Oct 05 '22 19:10

Luke Willis