Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplifying reducer with Actions restrictions and Immutability helper #688

Closed
yangit opened this issue Sep 4, 2015 · 6 comments
Closed

Comments

@yangit
Copy link

yangit commented Sep 4, 2015

Hi,

I'm thinking about using redux and here is what I came up with.
If we make an assumption that state is serializable, then actions on the state are basically as simple as set field, .splice, .push etc. Nothing much you can do with arrays and hashes anyway.
All of actions then could be expressed as React.addons.update mutations.

Now it seems beneficial to me to have low-level and high-level actions.
Low-level actions can only change state in a way React.addons.update does. I.e. simple hash\array mutations, one or few at a time.
And high-level actions can only change state via low-level actions. Because reducer would ignore anything except for lower-level actions.

That means that reducer is boiled down to:

var reducer = (state, action) => {
    if (action.type === 'update') {
      return update(state, action.mutation);
    } else {
      return state;
    }
  }

And reducer does not care about structure of the state any more.
Am I missing something?
What is the benefit of bothering with composing reducers etc?

Here is an example:

 var state = {
    isLoading: false,
    user: null
  }

  var action = {type: 'update', mutation: {isLoading: {$set: true}}};
  dispatch(action);

  //and later
  var newUser; //get it from somewhere
  var action = {type: 'update', mutation: {isLoading: {$set: false}, user: {$set: newUser}}};
  dispatch(action);

Higher level actions are just functions returning preset actions

  var actions = {
    setLoading: (value) => ({type: 'update', mutation: {isLoading: {$set: value}}})
  };

  dispatch(actions.setLoading(true));

With thunk middleware higher level actions could be composed too


  var actions = {
    setLoading: (value) => ({type: 'update', mutation: {isLoading: {$set: value}}}),
    fetchUser: () => (dispatch)=> {
      dispatch(actions.setLoading(true));
      getUserSomehow.then(newUser => {
        dispatch({
          type: 'update', mutation: {user: {$set: newUser}}
        });
        dispatch(actions.setLoading(false));
      })
    }
  }

With current approach shown in the docs we do not know what any particular action does, because it is received in many various reducers across the app.
With high-level actions we know exactly which lower-level actions are called from each higher-level action and we can be certain that we know how this action affects the state.
Is not it beneficial?

To be clear: I'm not in any way proposing changes to redux, I just would like to hear opinions on the way of using it.

@gaearon
Copy link
Contributor

gaearon commented Sep 4, 2015

I think a good way to find out if this abstraction is holding well is to reimplement real-world example with it. In theory, many things sound good, but often it turns out they are only good for simple examples, or that they are equivalent and push complexity from one entity (reducer) to another (action creator).

There have already been many discussions on “simplifying” Redux, most of which come down to “let's not use reducers and let action creators specify state mutations!” This sounds great in theory, but I'm not convinced this scales to large apps that have several people working on different features, with requirements like optimistic updates, data normalization, etc. Therefore I'm compelled to close this. A nice way to continue this discussion would be to re-implement real-world and other examples from Redux repo and demonstrate that whatever simplification you suggest actually simplifies these examples.

@gaearon gaearon closed this as completed Sep 4, 2015
@caesarsol
Copy link

I just searched if someone else did think to this approach!
@yangit have you jad any success?

@yangit
Copy link
Author

yangit commented Sep 22, 2016

gaearon was right :)
Do as he said.
My suggestion did not hold true after I tried it.

@markerikson
Copy link
Contributor

@caesarsol , @yangit : both of you may be interested in the new section I'm working on for the docs, on the topic of "Structuring Reducers". See #1784 for my planning and notes, and https://github.com/markerikson/redux/blob/structuring-reducers-page/docs/recipes/StructuringReducers.md for the current draft.

@caesarsol
Copy link

@markerikson that's very interesting, thanks!

@markerikson
Copy link
Contributor

Update: "Structuring Reducers" is now in the published docs, at http://redux.js.org/docs/recipes/StructuringReducers.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants