mangocaptain mangocaptain - 3 months ago 28
React JSX Question

How can non-normalized data cause problems in react redux?

Looking at the reddit doc example from redux, Dan says:

{
selectedSubreddit: 'frontend',
postsBySubreddit: {
frontend: {
isFetching: true,
didInvalidate: false,
items: []
},
reactjs: {
isFetching: false,
didInvalidate: false,
lastUpdated: 1439478405547,
items: [
{
id: 42,
title: 'Confusion about Flux and Relay'
},
{
id: 500,
title: 'Creating a Simple Application Using React JS and Flux Architecture'
}
]
}
}
}



In this example, we store the received items together with the
pagination information. However, this approach won’t work well if you
have nested entities referencing each other, or if you let the user
edit items. Imagine the user wants to edit a fetched post, but this
post is duplicated in several places in the state tree. This would be
really painful to implement.


Can someone explain what is the pagination information he is referring to? Also what would it look like if a user wants to edit a fetched post? How does that result in a post being duplicated in several places in the state tree?

Answer

I believe the lastUpdated property is the pagination data he refers to; it could be used (depending on the API) to pull changes made since the last update.

Your confusion regarding the normalization is understandable, because he doesn't include an example of a case in which the non-normalized approach is bad - though in the next paragraph of the documentation, he does provide an example of what a normalized structure would look like in a case that required it.

But consider this scenario: we're still managing a data set that tracks 'posts' which are parts of 'subreddits'. But now we're allowing for the possibility that a single post is 'cross-posted', and we're representing that as the same single post being contained in every subreddit object where it was cross-posted.

Let's say post 42 was cross-posted. Now the non-normalized state looks like this:

{
  selectedSubreddit: 'frontend',
  postsBySubreddit: {
    frontend: {
      isFetching: true,
      didInvalidate: false,
      items: [            {
          id: 42,
          title: 'Confusion about Flux and Relay'
        }
      ]
    },
    reactjs: {
      isFetching: false,
      didInvalidate: false,
      lastUpdated: 1439478405547,
      items: [
        {
          id: 42,
          title: 'Confusion about Flux and Relay'
        },
        {
          id: 500,
          title: 'Creating a Simple Application Using React JS and Flux Architecture'
        }
      ]
    }
  }
}

Now the user is looking at subreddit 'reactjs' and wants to edit the title of post 42. We should also update the title of the SAME post under subreddit 'frontend', but short of a full search of our state, we have no way of knowing that. So we're either going to undertake a costly search, or we're going to introduce a data integrity issue.

Normalized, this state would look something like:

{
  selectedSubreddit: 'frontend',
  posts: {
    42: {
      id: 42,
      title: 'Confusion about Flux and Relay'
    },
    500: {
      id: 500,
      title: 'Creating a Simple Application Using React JS and Flux Architecture'
    }
  },
  postsBySubreddit: {
    frontend: {
      isFetching: true,
      didInvalidate: false,
      items: [42]
    },
    reactjs: {
      isFetching: false,
      didInvalidate: false,
      lastUpdated: 1439478405547,
      items: [42,500]
    }
  }
}

Stored this way, the details of post 42 exist in only one place, and so they can be edited in one place and apply to every reference that might exist.

Of course, one could also use object references to accomplish this, putting the same object onto the arrays for both subreddits. However, that's not especially compatible with Redux, in which state alterations return new objects rather than mutating the existing. Using normalized references plays nicely with immutable data, which is an advantage for Redux state.

Comments