How do I structure my store for a master-detail view in redux?

Viewed 399

I'm building an email inbox using Redux. One half of the screen has a list of email subjects, and you can click one to view the full email contents on the other half of the screen. Most devs would call this a "master-detail" type application.

An email that is displayed in the "master" list (it's a class in my app called SimpleEmail) looks like this. The model has been shrunken down to reduce the amount of data transmitted when fetching a list of possibly 100+ emails.

{
  from: "hello@site.com",
  subject: "Hello, Jon",
  id: "abc123"
}

An email in the "detail" list (a class called EmailDetails) has a model that is way more complicated and has a different shape.

{
  id: "abc123"
  headers: {
    from: "hello@site.com",
    subject: "Hello, Jon",
    to: [],
    bcc: null,
    cc: null,
    replyTo: // and about 10 more fields
  },
 bodyHtml: "This is some text",
  attachments: [],
  receivedAt: null,
  // and about 10 other fields
}

How should I shape my application state in redux to handle these two different models being used? My initial thought is to do the following:

{
   emailMaster: {
     entitiesById: {},  // a Map of emails keyed by ID
     ids: [],
     selectedId: null
     isFetching: false,
     isError: false
   },
   emailDetails: {
    selectedEntity: {},   // A single email object
    isFetching: false,
    isError: false
   }
}

I can already see a couple issues with my design:

  • The data is not normalized, and thus, there is duplicate data. This violates a major design principle of redux.
  • If a user updates an email (such as marking it as unread), I will have to check to see if that email is loaded in the "detail" view, and update the second model. This seems like a code smell.
  • There is no single source of truth for which email ID is selected. What if there is a race condition (maybe the user is clicking around the screen really fast) and emailMaster.selectedId is a different value from emailDetails.selectedEntity.id? Again, this seems like a code smell.

Something obviously doesn't feel right. Is there a better way I could go about designing the shape of my application state?

0 Answers
Related