DEV Community

Explain Redux Like I'm Five

Johnson Ogwuru on March 25, 2019

I'm having a hard time understanding the core concepts of redux in react, anyone cares to explain to me or point me to an amazing article or video on this?

Thanks

Collapse
 
rhymes profile image
rhymes • Edited

Hi Ogwuru, Redux is not an easy thing to tackle, this and the other comments should help :)

I'll try to introduce the core concepts of Redux (store, actions, reducers, subscriptions) with a super simple example.

Initial state

Let's say you have an apple. The apple represents your application's current state in time. Let's define the apple as a JS object:

const initialApple = {
  dirty: true, remainingBites: 5, color: 'red'
};

Actions

There are many things you could do with the apple, and every action may change the apple slightly.
Let's define the possible actions you could perform:

const WASH = {type: 'WASH'};
const EAT = {type: 'EAT', bites: 2};
const ROT = {type: 'ROT'};

Reducer

We can now define a reducer function to handle these actions:

function appleReducer(state = initialApple, action) {
  switch(action.type) {
    case 'WASH':
      // sets the `dirty` field to `false`
      return {...state, dirty: false};

    case 'EAT':
      // decrements the number of remaining bites (cannot go below 0)
      // note that the number of bites is given as a payload in the EAT action
      return {
        ...state,
        remainingBites: Math.max(0, state.remainingBites - action.bites)
      };

    case 'ROT':
      // changes the apple's color to brown
      return {...state, color: 'brown'};

    // we don't know how to handle other actions,
    // so let's just do nothing and return the apple
    default:
      return state;
  }
}

Every time we perform (or dispatch) an action, the resulting apple object is slightly different from what it was before the action.

Store

Now that we have a reducer (list of possible actions) and an initial state (the apple), let's create a store and provide the apple as the initial state:

const store = Redux.createStore(appleReducer, initialApple);

To retrieve the apple object at any time, we can use store.getState(), which returns

{
  dirty: true, remainingBites: 5, color: 'red'
}

Subscribe

Let's also subscribe to any changes to the apple:

function handleChange() {
  const currentAppleState = store.getState();
  if (currentApple.color === 'red') {
    console.log('Looks delicious!');
  } else {
    console.log('Looks awful, better throw it in the bin!');
  }
}
store.subscribe(handleChange);

Async actions

This timer starts when we first buy the apple and waits a whole week before dispatching the ROT action:

const weekInMilliseconds = 1000 * 60 * 60 * 24 * 7;
setTimeout(() => {
  store.dispatch(ROT);
}, weekInMilliseconds);

I hope you know how this works, but as a refresher: setTimeout takes two parameters: a function and the number of milliseconds to wait. After the number has passed, the function is called.

Dispatching actions

Now, let's do stuff with the apple.

Before all the actions:

// store.getState()
{
  dirty: true, remainingBites: 5, color: 'red'
}

After washing (store.dispatch(WASH);):

// store.getState()
{
  dirty: false, remainingBites: 5, color: 'red'
}
// console
Looks delicious!

After eating (store.dispatch(EAT);):

// store.getState()
{
  dirty: false, remainingBites: 3, color: 'red'
}
// console
Looks delicious!

After eating again (store.dispatch(EAT);)

// store.getState()
{
  dirty: false, remainingBites: 1, color: 'red'
}
// console
Looks delicious!

Let's forget about the apple for a while.

Oh, right — we used setTimeout to wait for a week. Once that resolves, the ROT action is dispatched and the resulting apple is this:

// store.getState()
{
  dirty: false, remainingBites: 1, color: 'brown'
}
// console
Looks awful, better throw it in the bin!

After washing, taking 4 bites and then waiting a week, there's not much left of the apple, but hopefully you understood the basics of Redux.

You can find the whole conversation here:

Collapse
 
ogwurujohnson profile image
Johnson Ogwuru

Thanks Rhymes would go through it

Collapse
 
vallerydelexy profile image
vallerydelexy

how a 5 yo could possibly understand this..

Collapse
 
rhymes profile image
rhymes

Ahah you have a point

Collapse
 
vier31 profile image
Jan Schröder • Edited

Let's say, we have to tend to a vertical garden like the one below.

Vertical Garden pyramid

Now, for some silly reason, we can only water the top row. In order to get the water and the fertilizer down to the bottom row, we have to pass them through each row.

This would get pretty tedious rather quickly, no? Wouldn't it be nicer if we had a separate water tank, from which we can hydrate each flower individually, with exactly the amount of water and the exact minerals needed.

It's the same with React. Information can only be passed downwards in the component chain. So as soon as we have to pass props down for three or more layers, it becomes cumbersome. That's where Redux comes in. It provides an independent 'store' for information, that we can access from any level in the component chain.

So you can pass props from one component via the store to another component.

The function we use to access the store and get information are called Reducers.

In order to update the store, i.e. change the state of the store, we dispatch an Action.

Collapse
 
ogwurujohnson profile image
Johnson Ogwuru

Thanks alot for the explanation, I'm getting to understand it better now

Collapse
 
aimerib profile image
Aimeri Baddouh

All the explanations here are really solid, but what really helped me finally understand was this:

code-cartoons.com/a-cartoon-intro-...

Not quite suitable for a 5 years old, but it goes into a lot of why Redux is relevant. Also, if you haven't reached the pain-point of needing to do global state management yet, it will be harder to understand how this even works. My suggestion would be to learn as much as you can the best way you can for now, since you're curious, but just as with any tool, don't try using it before you need it.

Collapse
 
ogwurujohnson profile image
Johnson Ogwuru

Thanks for the advice

Collapse
 
zeddotes profile image
zeddotes
  • Your entire app relies on 1 data object, called the store.
  • There are 2 main functions on the store: read actions and mutate itself depending on the actions (reducers).
  • You can "dispatch" (or add) an action to the store. Once you have, all your defined reducers will run.
  • Your reducer functions are basically switch/case statements for the type of action. Once you've matched with an action, your function is to return the mutation.

An example, let's say your store is { user: "johnson1" }:
dispatch({ type: "LOG_OUT" }) -> reducer match of action "LOG_OUT" -> return { user: null } -> redux updates store

Collapse
 
ogwurujohnson profile image
Johnson Ogwuru

Thanks alot for this, I appreciate

Collapse
 
niorad profile image
Antonio Radovcic

You make a list of every friend you have and give them a number how much you like them.

Tommy: 5
Billy: 3
Sara: 2
Zak: 8

You write down all the things your friends could do, and how it would change their number.

Giving me a doll: +1
Breaking my toy-car: -2
Inviting me to a birthday: +3

Sara gives you her transformer-doll.

Now you like Sara more (+1).

Instead of striking out the number on your old list, you decide to write a new list, with the current numbers.

Tommy: 5
Billy: 3
Sara: 3
Zak: 8

You do this every time you like a friend more or less.

You keep all the old lists in your folder, so you can see which friend you liked more or less in the past.

Collapse
 
brittneypostma profile image
Brittney Postma

This is the link to my article, it might help.
dev.to/bdesigned/explain-redux-lik...

Collapse
 
ogwurujohnson profile image
Johnson Ogwuru

Thanks, great article. Love your approach to redux.