4

What is the best practice for structuring the state object in Redux in relation to related objects.

Example:

User has-one Organisation

With the above schema, where we also have a list of organisations is the following example a good idea?

{
    user: {
        id: 1,
        organisation_id: 3,
        first_name: 'Andrew',
        last_name: 'McLagan',
        email: '[email protected]',
        organisation: {
            name: 'Foo Bar Co.'
            suburb: 'Booklyn',
            phone: '123-123-000',
        },
    },
    orgnaisations: [
        {
            id: 1,
            name: 'Facebook'
            suburb: 'Booklyn',
            phone: '000-000-000',
        },
        {
            id: 2,
            name: 'Twitter'
            suburb: 'Manhattan',
            phone: '456-456-000',
        },
        {
            id: 3,
            name: 'Foo Bar Co.'
            suburb: 'Booklyn',
            phone: '123-123-000',
        },
        {
            id: 4,
            name: 'Some Org.'
            suburb: 'Bronx',
            phone: '642-642-000',
        },                      
    ]
}   

Or would it be better to access the users organisation by:

const organisation = state.organisations[user.organisation_id];

1 Answer 1

1

I think it is better to access the user organizations through their ID. Here is a possible way to organize your state:

{
  user: {
    id: 1,
    first_name: 'Andrew',
    last_name: 'McLagan',
    email: '[email protected]',
    organization: 3,
  },
  organizations: {
    1: {id: 1, name: 'Facebook', suburb: 'Booklyn', phone: '000-000-000',},
    2: {id: 2, name: 'Twitter', suburb: 'Manhattan', phone: '456-456-000'},
    3: {id: 3, name: 'Foo Bar Co.', suburb: 'Booklyn', phone: '123-123-000'},
    4: {id: 4, name: 'Some Org.', suburb: 'Bronx', phone: '642-642-000'},
  }
}

Using vanilla Redux

If you want to get the current user and his organization, you can use the following selector:

function mapStateToProps(state) {
  return {
    user: state.user,
    organization: state.organizations[state.user.organization]
  }
}

The direct access using its ID will be a performance win. You can still easily query all stored organizations:

function mapStateToProps(state) {
  return {
    organizations: Object.values(state.organizations),
  }
}

Using reselect

If you care about performance, using reselect would be a huge win. The first step is to define your selectors:

// Get a list of all organizations
const getAllOrganizations = createSelector(
  state => state.organizations,
  orgs => Object.values(orgs)
)

// Get the current user
const getUser = state => state.user

// Get the current user's organization
const getUserOrganization = createSelector(
  [
    state => state.user,
    state => state.organizations,
  ],
  (user, orgs) => orgs[user.organization],
)

You could now use those selectors to update your mapStateToProps functions. The two described above would be:

// Get the current user and his organization
function mapStateToProps(state) {
  return {
    user: getUser(state),
    organization: getUserOrganization(state),
  }
}

// Get all organizations
const mapStateToProps = getAllOrganizations
Sign up to request clarification or add additional context in comments.

4 Comments

:-) awesome. One Question... What about if there is only ever a single organisation. THEN is it ok to nest it in user
@AndrewMcLagan I guess yes. But the more you normalize your store, the easier it will be to manipulate it.
okay, this makes me excited. One last question. For myself and other SO users can you point us to the location of an article or documentation on this pattern?
The section Computing Derived Data in Redux's doc explains this pattern.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.