post cover

HOW TO USE REDUX WITHOUT LOSING YOUR MIND - PART II

January 02, 2020

In the last part How To Use Redux Without Losing Your Mind I’ve presented the new way of using redux libary.

The main reason behind implementing a custom way of using Redux was the endless writing a code of action creators, action types, extracting them to separate files, writing one reducer with huge switch cases - I was so tired with writing that type of code and I wanted to finally simplify it. In the first part, I wrote about how it’s possible to write much less code with the same result. I am successfully using it in my own project - and no, it’s not a simple TO-DO list with a few actions. It is a huge application with hundreds of endpoints and “global” state attributes in redux - which had to be set. With that approach, I had zero problems and development felt much faster.

In the end - You want just setState and you just want your application to depends on your state. Just like in your simple react component.

const Comp = () => {

  const [value, setValue] = useState("");

  return (
    <div>
      <input value={value} onChange={(e) => setState(e.target.value)} />
    </div>
  )
}

Well, maybe I said that but: simplicity and no more useless code! I just want to set that freaking state.

I am so glad I don’t have to write different actions and action creators for fetching states:

  • FETCH_START
  • FETCH_DONE
  • FETCH_ERR
  • … and other stupid things, this is just… a lot of code to bother with.

However, when your application grows and you want to keep your code separated, or different components need to communicate with each other, then it’s a good idea to use global state management library - such as Redux. Nowadays, you can use Context. But I found Context to rerender a lot and it is a lot harder to optimize components within Context. With Redux, you can easily optimize selection of attributes from global state if you need. For such things, it is good to use selectors from library reselect.

Note: If you application is small and your global state isn’t changed too often, then Context is in my opinion right for you - otherwise, use Redux

Enhancement of the previous solution

In the last part, I presented the solution where the value of the reducer was simply set within a function, such as this:

import update from "immutability-helper";
  
const { postsState } = store.getState();

newState = update(newState, {
  fetch: {
    loading: {
      $set: true,
    }
  },
});

setPostsState(newState);

function setPostsState is doing everything for us. Dispatch a setting function for the reducer. However, this one got one disadvantage. If between line where store.getState and setPostsState happened something, where state was changed, we would run into race condition - we would overwrite new state with the old state values. So I came with the new idea, where you don’t have to getting state anymore.

Now you can write the action like so:

import update from "immutability-helper";

setPostsState(oldState => {

  // returning the new state
  return update(oldState, {
    fetch: {
      loading: {
        $set: true,
      }
    },
  })
});

And how the reducer was changed? Not much.

  // reducer.ts

  const defaultState: PostsState = {
    posts: [],
    fetch: {
      error: null,
      loading: false,
    }
  };

  const postsReducer = (state: PostsState = defaultState, action: PostsActions) => {
    switch (action.type) {
      case "SET_POSTS_STATE":
        return action.payload(state); // instead of return action.payload;
      default:
        return state;
    }
  }

Not very different from previous version. But now, we are depending on the state value provided by reducer itself. In the payload is the function that we send within our action setPostsState. This function gets into the reducer. Reducer passed actual state inside the function and function just did it job and returned new state which was finally set by reducer.

With typescript, it is much safer to do these type of operations because this passed function MUST always return valid PostsState type.

Conclusion

You don’t have to keep align with official redux guide. In my opinion, official approach requires a lot more code to be written - which is often unnecessary. My recommendation is, if you understand how redux works, try to play with it a little bit and find a way which works for you. I figured my own way which works in my application without problem. The development is a lot faster, reduces code and complexity.


Join the Newsletter

Name
E-Mail