Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React-Redux State Shape for multiple pages

I'm trying to design an admin panel website using redux and react that performs basic crud operations on REST resources. I think I'm starting to understand redux, but I'm not quite sure how to structure the state shape, in particular when storing different data per page. For example the login page will store different data than the page to edit a user for example.

I came up with the following "schema" for my state shape:

var schema = {
    //Things applicable to the authenticated used
    authentication: {
        authenticated: true, //True if a user is authenticated
        auth_user_id: 2, //ID of the authenticated user
    },
    //Things applicable to the layout of the application, for example the notification menus that can be toggled on and off
    layout: {

    },
    //Things specific to each page of the application
    pages: {
        //Login page (eg https://example.com/login)
        login: {
            isFetching: false, //Is data loading?

        },
        //Data pertaining to the page that shows list of users (eg https://example.com/users)
        userList: {

        },
        //Data pertaining to the page to edit a particular user (eg https://example.com/users/:id/edit)
        userEdit: {

        }
    },
    //Normalized entities are stored here.
    entities: {
        usersById: {
            2:
                { //User ID
                    id: 2,
                    first_name:
                        "Some",
                    last_name:
                        "User"
                }
        }
    }
};

I would then have a reducer for each "page" in the pages tree. Is this the correct way to handle this? I can't seem to find any examples or tutorials on how to structure a larger application that isn't just a simple page that toggles between a couple of views.

like image 324
Brad Avatar asked Jun 05 '18 15:06

Brad


1 Answers

TL;DR / Summary: Yes, your solution seems consistent with general data architectural norms for applications with significant user interface components. However, you may also want to consider some internal component state as well.

This is a general problem in data structures and software architecture, particularly around user interfaces. There is no one-size-fits-all answer for this; it will always depend on the specifics of the application and the data on which it operates. I can attest that I have worked professionally on multiple projects (including a current React project, as well as Angular and Backbone) with data structures similar to the one you describe -- i.e. a mixture of both view-centric and normalized data.

Early on I encountered the question developing Java Swing applications, where the question was framed as component (view) hierarchy (a.k.a. containment hierarchy) vs. object (data) hierarchy (not to be confused with class or inheritance hierarchy) -- and when the latter (data) should mirror the former (views) or not.

I now more generally think of the problem as designing the data hierarchy with the view hierarchy in mind.

Some reasons for having portions of the data hierarchy (in the top-level state/store) mirror the view hierarchy:

  • Data is very view-specific, representing things on a screen, in natural language, or from user input
  • Data will not be reused or shared by other areas of the application
  • Data represents ephemeral UI-only state, perhaps cached for a few minutes but not permanently

Some reasons for having portions of the data hierarchy more normalized and unrelated to view hierarchy:

  • Reduction of duplication (DRY principle)
  • Data will be reused or shared
  • Data represents longer-term state not so closely tied to UI, perhaps duplicated in browser storage

With Redux in particular, some data is so ephemeral or transient that it does not belong in the top-level state/store at all. This data could be kept in component state, which also keeps the store more slim and focused.

Some reasons for having portions of the data local to component state:

  • Data is 100% view-specific
  • Data should be hidden/encapsulated from other areas of the application; perhaps it is for a higher-order component, or a component that is generic and highly reusable (the component logic itself -- not the data)
  • Data represents strictly ephemeral or transient UI-only state

Interesting blog entry with extended analysis of using top-level store state vs. component-level state:

  • 3 Things I Learned About Working with Data in Redux by Nick Cantelmi
like image 74
Will Avatar answered Nov 15 '22 16:11

Will