简体   繁体   中英

Best Practice: Handle read-only data with Redux

I am building an application with React and Redux and I have a question about design.

My application uses React Router. It has a Navigation Bar (on the left) that displays the routes from React Router configuration file with a Material Design Menu.

I would know what is the best practice to handle the static data of this LeftNav component.

This data has the following shape:

const menuItems = [
  {
    icon: 'home',
    label: 'Home',
    url: '/home',
    withDivider: true,
    access: 'all',
  },
  {
    icon: 'settings',
    label: 'Settings',
    url: '/settings',
    access: 'admin',
  },
  {
    icon: 'power_settings_new',
    label: 'Log Out',
    url: '/logout',
    access: 'user',
  },
];

To respect the smart and dumb component proposal , my LeftNav component is dumb and stateless. I also have a smart component (right now it's just my AppContainer ) that renders the LeftNav component and provides the menuItems array to it via props.

I wonder if I must include this read-only data into my redux state tree. In this case, I would have a constant reducer like this:

export default handleActions({}, [
  {
    icon: 'home',
    label: 'Home',
    url: '/home',
    withDivider: true,
    access: 'all',
  },
  {
    icon: 'settings',
    label: 'Settings',
    url: '/settings',
    access: 'admin',
  },
  {
    icon: 'power_settings_new',
    label: 'Log Out',
    url: '/logout',
    access: 'user',
  },
]);

Is it a good practice to have a constant reducer with no action handler? If not, what should I do?

Thanks in advance.

I'm not recognizing how your reducer is working. What is handleActions ?

I think a constant reducer seems like a reasonable solution, but I would implement it by using a default first parameter. Assuming you're using combineReducers to scope all your reducers to the part of the state they control, I'd do something like:

/* reducers.js */

const menuItemsInitialState = [
  {
    icon: 'home',
    label: 'Home',
    url: '/home',
    withDivider: true,
    access: 'all',
  },
  {
    icon: 'settings',
    label: 'Settings',
    url: '/settings',
    access: 'admin',
  },
  {
    icon: 'power_settings_new',
    label: 'Log Out',
    url: '/logout',
    access: 'user',
  },
];

export function menuItems(state = menuItemsInitialState, _) {
  return state;
}

Personally I prefer my reducers to focus on dealing with application / system-wide state. The configuration in your example would feel more at home living as a constant inside the component which makes use of it ( LeftNav ?)

@Cnode I agree @acjay that it should be in reducer state , even without action creators.

I would go one step further and suggest that you should fetch the data after the app loads rather than including the data in your built files. Generally data does not belong in built files .

This is because, in the real world this particular set (and others - possibly much larger sets) would be statically available on an API as you probably would want the values configurable by a CMS.

  1. Add a static reducer to host this state
  2. Fetch the data after the app initialises and then push it on state - meaning you will have at least one action creator.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM