Redux is silly and hard to remember the patterns. Can anyone help me get past rote memorization or do I need to suck it up?

Tell us what’s happening:
Redux seems to break free of JS Syntax and doesn’t make sense to me. This is my 3rd or 4th time trying to learn it and I just don’t understand this code.

I can READ the code adn see that it works, but there is a lack of parallelism between returning “true”, “false” and the defaultState

For example, why doesn’t the LOGIN case return { defaultState: true } instead of just true? With more complex state, how do you differentiate the object entries?

and if the default just returns the original state why is there a need to return it? It seems redundant.

I’m not saying I don’t understand this…I’m saying i need a way to hook this syntax into my memory so I can progress moreo easily.

If the answer is ‘This is a different type of pattern and syntax and you just have to memorize it’ that’s fine too, but it is just not sticking !

  **Your code so far**

const defaultState = {
authenticated: false
};

const authReducer = (state = defaultState, action) => {
// Change code below this line
switch (action.type) {
  case "LOGIN":
    return {
      authenticated: true
    };

  case "LOGOUT":
    return {
      authenticated: false
    };

  default:
    return defaultState;
}
// Change code above this line
};

const store = Redux.createStore(authReducer);

const loginUser = () => {
return {
  type: 'LOGIN'
}
};

const logoutUser = () => {
return {
  type: 'LOGOUT'
}
};
  **Your browser information:**

User Agent is: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.55 Safari/537.36

Challenge: Use a Switch Statement to Handle Multiple Actions

Link to the challenge:

The title of this post and the specific example do appear to be separate questions, perhaps worthy of separate posts. I will respond to each separately.

I keep notes of common problems that I run into. I also have a note that says “action, reducer, combineReducers, mapStateToProps” because that is common in my workflow and yet I have problems remembering it. Even after years programming professionally, there are things that I forget, so I make notes.

This const defaultState holds the value “{ authenticated: false }”, so it should not ever return “{ defaultState: true }” or “{ defaultState: false }” or even “{ authenticated: true }” - it is constant, meaning that it does not change. If you were to access defaultState[‘authenticated’] or defaultState.authenticated you would only get “false”. If you are getting other return values, then it is not that defaultState that you are getting. You could even assign another variables like state to the value stored in defaultState, and change the value stored in state later, or return something else entirely, but again the idea of a const is that it does not change. I know that doesn’t answer your question exactly - I do not know what is meant by “parallelism” in this context - but hopefully it helps clear up at least part of it.

2 Likes

Redux, certainly using the library directly without any of the newer developments around it, does tend to mean a bit of boilerplate code. But that required boilerplate code also happens to be extremely basic JS, it has very little complexity itself. What code in the snippet you’ve posted do you think isn’t that?

Thanks Dan, it’s for some reason looking and feeling different to me than any other function with an object passed in.

The variable state is not being specifically accessed in the solution snippet.

So how does the compiler know where “authenticated” comes from as opposed to state.authenticated?

From the answer above yours I now see that the default return statement in this case is literally a “factory reset” to return the constant.

Does that question/confusion point make sense to you ?

In react we would be using this.state. Authenticated or this.props.etc

What are some of the newer developments around redux like you may have suggested?

I really like react but feel I’m limiting my development by not learning redux too.

Maybe I need a different library that will make more sense or a different set of tutorials. I’ve tried the redux tutorials as well in the past.

Thank you this explanation makes sense on both parts. And it’s refreshing to know you have reminder notes!

I understand the default state in this example now better.

Still a little confused on why this code can return just authenticated:true and not this.state.authenticated.

How does the state object being passed in get accessed inside this function without using its name?

I would suggest you look up more resources on the library and read the docs. Only using fCC to learn it might just not be enough.

One of the reasons going throught react and further more redux can be so difficult, is not only that they use advanced manipulations with functions, methods and object, but those are often ES6+ syntax and when you are new with JS and have little practice, all that chain passing of data trhought function parameters can be really hard to follow.
My advice to you is first, dont feel obligated having to fully understand or apply redux, its something you would need for advanced projects and in the case of the FCC ones, its not required at all. There will be time and place, you will want to try and apply redux and when that times comes, you can come back to those lessons, or look up in google for the docs and guides and slowly process them while working in authentic environment. For now, its enough to just have some general understanding what the subject is, to know its there and its available to you, when you eventually need it.
Another major factor in those lessons(and possible hardship), as i mentioned, is the advanced manipulations with objects/methods etc, which i find at this stage, even more important to learn, as its the basic for everything. All those frameworks are based using that extra feat of JS and the more comfortable you feel using all the features JS can offer, the easier for you will be to read, understand and adopt as your own those same frameworks and techniques. Just read the lines of the code, there is a function with default parameters, where state parameter is assigned an object; there is an action parameter, which expects an object passed, with a property of type. There is the switch syntax, which is meant to return the final value of this same function, which is also always in the shape of an object, as thats what redux state is meant to be- an object. Further, there are the action creators, which are just functions returning the object, which holds instructions regarding the action the reducer should execture with the state, always containing the property type. In the end you get the Redux object, of which you call the createStore method and pass it the reducer function…The more comfortable you become with working with functions, methods, objects etc, the easier it will be the read the flow of that or any code, so besides looking for additional info on how redux operates, its of key importance to stay on top of your game regarding working with those basic JS features.

Thanks for these links. I started with the docs figuring that would be best but something about it just doesn’t come as easily as the rest of what I’ve learned. I admit react was hard at first, and I used an outside course or two and only recently went through FCC to refresh myself on React and it seemed easy. I’ll check these out again, and I’ve not heard of the I2, so sounds cook.

THanks I agree ES6 is newer to me and sometimes hard to implement for me. Here is one example though that has me still head scratching:
If we just use this simple code why is “type” accessed with action.type, but “authenticated” is not accessed with state.authenticated?

I think my confusion boils down to this right now.

const authReducer = (state = defaultState, action) => {
switch (action.type) {
  case "LOGIN":
    return {
      authenticated: true
    };
}

Where do you try to access it? If you console.log(state.authenticated) inside the authReducer, where state variable exist, it will return the value. The action exists in the given context, so you can access its properties just the same(within the authReducer). The actual state object, is contained within the store, which we declare here const store = Redux.createStore(authReducer). The createStore method creates the store object, which is meant to store our state. We can access its value with its own method, getState()(you call it as store.getState()). If you console.log(store), you will notice the store object has few methods, one of which is dispatch, which is the one you use to dispatch or apply actions to the store, e.g. you can dispatch the action creator loginUser, which will pass to it the action with type “LOGIN” and trigger the respective mechanics.

PS: in case i did misunderstand you, we dont access state.authenticated because that value does not concern us, we want to give it a new value. The reducer is meant to return a new state object, not mutate the existing one. It works with the store, where our state is kept

The function takes an argument and returns a new value of the same type, this is how it works. If the argument is { authenticated: false } and you mutate the property then it isn’t returning a new value, it’s either returning the same value (if you return state) or returning undefined (if you only mutate the value then break). This is what I mean by it just being basic JavaScript. The only things that are ES6 (which, note, is just normal JS at this point in time, it hasn’t been new for 7 years now) are the default parameter and the fact it’s an arrow function,

function authReducer (state, action) {
  state = state || defaultState;
  switch (action.type) {
    case "LOGIN":
      return {
        authenticated: true
      };
  }
}

OK, this is starting to make sense now. I see what you mean by it being basic JS. Somehow I was expecting something closer to setState…but I guess it’s not really any different.

I think once I understand the context in which the reducer is called, it will start to make even more sense.

Thanks for taking the time to write this out (again).

Also…I joined FCC in 2014 or something…so ES6 was new or maybe even non-existent then!

All I do is goof around and try to build my own projects so I have no external timeline to compare to.

1 Like

There’s an alternative to redux called context which is easier to implement but does the same thing (global state management) and is part of the react api so you don’t need external libraries.

essentially you can just move state management code out of your components into a global file and import it to the components that need it. these videos explain it well.

isnt context purpose to give access to indirectly connected components to common state, while redux purpose is to organize this state under more comfortable shape to manage, the two should rather work in union. React also does offer its own useReduce hook(when it comes to hooks syntax), which is quite similar to redux and wont require you to upload additional libraries.
Anyway the purpose of this topic is not for best practices and additional tools, but to lighten the FCC react-redux lessons

I mean yeah I’m sure it can turn into quite a long technical debate, the point I was making is that there are easier ways to manage global state than redux and as the OP seemingly doesn’t like using redux he might be more comfortable using context for this purpose, as the redux sections aren’t mandatory for the completion of the projects in the frontend certificate.

1 Like
function createStore (reducer) {
  let currentState = reducer();

  return {
    getState() {
      return currentState;
    },
    dispatch(action) {
      currentState = reducer(currentState, action);
    }
  };
}

There is another function called addListener that gets returned, but the above code is the key part. Bar that extra function, Redux is not more complicated than that :point_up:

Note that currentState also starts as undefined in the actual Redux code, and the createStore function sends a dummy event into the reducer to kick everything off, rather than what I’ve done on the first line of the createStore function. Has the same effect here though.

So, taking your current example:

const defaultState = {
  authenticated: false;
}

function authReducer (state, action) {
  state = state || defaultState;
  switch (action.type) {
    case "LOGIN":
      return {
        authenticated: true,
      };
    case "LOGOUT":
      return {
        authenticated: false,
      };
    default:
      return state;
  }
}

So

const store = createStore(authReducer)

So

  • currentState is the value of reducer, called with no arguments. That means it’s reducer(undefined, undefined). So it returns the default, which is defaultState.
  • the createStore function returns an object with two methods.
  • getState() returns whatever currentState is
  • dispatch(action) sends an action in and runs the reducer, so
store.getState()
// { authenticated: false }
store.dispatch({ type: "LOGIN" })
store.getState()
// { authenticated: true }
store.dispatch({ type: "LOGOUT" })
store.getState()
// { authenticated: false }
// Send an unrecognised event,
// The reducer just returns the current state
store.dispatch({ type: "FART" })
store.getState()
// { authenticated: false }
1 Like

Yeah, for very simple global state like authentication (eg user is authenticated/user is not authenticated). Redux is for managing complex global state, like data from APIs. When used with React, Context alone isn’t going to make that any easier because doing so is just going to involve hand-rolling a version of Redux/similar state container. Not that that is a huge issue given how trivially simple Redux is, it’s just a bit pointless and means lots of fighting to fix rerendering issues that react-redux has already solved (and Redux’ React bindings have always used the Context API, that’s how they can function)

1 Like

Create a reference react- redux codes.

So that every time you are going to create a react-redux app, you already have the base codes.

For your questions:

[In my opinion or how I understand]
Reducer have 4 basic components:

  1. State - stores your information, this is an object.
  2. Reducer - brain of your Redux, this needs to return the updated state or the current state
    - looks on the action as an indicator, to be use in your logic (switch-case)
    - you can optionally set your created State as default value
  3. Action - which handles the passed information, before the Reducer decides to put into your state.
    - Reducer heavily rely on the type of the action (see switch-case in your code)
    - you can also pass an information here to be use by the Reducer using action
  4. Store - which will connect your Redux to your React,
    - you need to specify which Reducer you are going to use

Sample:
Set constants
const CHANGED = 'CHANGED'

Set action to be used by the store
made sure that the type used in your action is also used by the Reducer, or else it will do nothing

const actionChanged = ( ) => {
  return {   
     type: CHANGED,
  }
}

Set default values for state
const myState = { changed: false }

Create your reducer

const reducer = (state = myState, action) => {
   //make a duplicate state
  const newState = Object.assign( {}, state );
  switch (action.type) {
      case CHANGED:
           newState.changed = !state.changed;
           return newState;
      default:
           return state;
  }
}

Put reducer to store
const store = createStore(reducer)

Tell the app to do something with your state
store.dispatch(actionChanged())

Result
store.getState()
#result: { changed: true }

Advance:
The Store can have multiple Reducer using combineReducers

1 Like

This is great, I will definately try this for a few simple projects. I implemented a command line app for react components (trot - npm)

And it was helpful for sure.

Thanks for breaking it down