carloabelli
carloabelli

Reputation: 4349

How to Structure Normalized Redux Store When Loading Data

I am trying to create a React/Redux app which lists books. Each book then has related books. I know I should structure my redux store in some sort of normalized fashion like so:

{
  books: {
    'book1id': {
      title: 'Book 1',
      author: 'Author 1',
      relatedBooks: ['book2id', 'book3id']
    },
    'book2id': {
      title: 'Book 2',
      author: 'Author 2',
      relatedBooks: ['book1id']
    }
  }
}

and load each book as necessary.

The issue is where to store loading/error data from the API requests? Some ideas I had were to create an object for every book such as

books: {
  'book1id': {
    isLoading: false,
    error: null,
    book: {
      title: 'Book 1',
      ...
    }
  },
  ...
}

But that seems to detract slightly from the readability/intuitiveness of the state. Is there a better way to structure the state?

Upvotes: 2

Views: 741

Answers (1)

Jonathan Spengeman
Jonathan Spengeman

Reputation: 26

I structure my redux store so that it includes an entities object for all of my relational data and I store things specific to a page or a set of routes in separate parts of the state. My state tree might look something like this:

const state = {
  entities: {
    books: {
      ...
    },
    authors: {
      ...
    },
    ...
  },
  booksPage: {
    isLoading: false
  }
} 

Now I am keeping track of my relational state separate from the state of my UI components. I would not recommend trying to store a isLoading state in an individual entity since that entity may or may not exist. If you need more granular loading/error state on a per entity basis then rather on a set of entities you have a few options. The first option is keep a set of IDs that are currently loading. This is not a very practical solution because you can't track success or failure with an ID simply being in a set or not.

The next, better solution is to keep a map from ID to a status object that includes if an individual entity is loading, if it was successful or if it failed to load and what the errors were.

const state = {
  entities: {
    books: {
      ...
    },
    authors: {
      ...
    },
    ...
  },
  booksPage: {
    loading: {
      book1: {
        status: 'FAILED',
        error: 'Network request failed.'
      },
      book2: {
        status: 'SUCCESS',
      },
      book3: {,
        status: 'IN_PROGRESS'
      }
    }
  }
}

In summary, I find separating out your relational state into an entities child object while having page specific sections of state to be working quite well for me.

Upvotes: 1

Related Questions