In this video we must talk about Usereducer.
Why is that?
Because in previous video we talked about use state and this is totally fine.
But even for our not huge project, we need something better.
Why is that?
As you can see here, we're using your state to store, index and update it.
But what if we have more properties?
Maybe we need to store an array of our questions.
Additionally, we might store some login indicator or active questions, or already selected questions,
which actually means we will copy paste this line and create in our component a lot of use state in
one of them we are storing questions in.
Next we are storing correct answers and so on.
It might be tedious and it is difficult to manage, but at this point you for sure want to say okay,
but we can do better.
We can store an object.
And for example, here instead of this zero, we can create an object and we are providing insight.
For example current question index is zero.
And let's say we want to store here our array of questions.
And by default it will be an empty array.
Then what we are getting here is our state and set state.
Now instead of creating lots of different properties, we simply handle an object with row inside different
properties and we are good to go.
Now here, instead of our question index, we can write state dot current question index.
This is totally fine.
And now here is the place where we will have problems.
Because here we must write set state and we must provide here a new value.
But as you can see, we don't have just new value here for the index.
It is the whole object which actually means we must provide here an object, and we must spread the
whole state that we have now.
And now we want to override something like for example, current question index equals state dot current
question index plus one.
And as you can see this code is much less readable.
It's not really clear what we are doing here.
And if we want to change lots of different properties then it is difficult to follow.
Like for example, our next questions will do a lot of stuff and not just change index.
This means that here we must update lots of different properties, and it is not really clear that it
is related to our next question.
So you state is awesome for simple cases, but if you want to have strict structure, then I highly
recommend you to look on Usereducer.
And the idea of Usereducer is coming from Redux.
And bear with me because this video will be a little bit complicated.
The main idea of Redux was that we have a single flow of data inside our application, and we define
the view.
This is our component.
We have actions.
This is exactly something which changes our state.
Like user clicked on this button, or user selected something from the menu.
And we have our state which we really want to update.
Then every single time when our state changes, our view knows about it and it renders our component.
Usereducer is exactly the implementation of Redux that we can use to have a strict structure.
This is why what I want to do here, I want to remove completely use state and this sets that we don't
need.
And additionally I want to remove this property after our next question.
So now everything is clean.
We need to start again.
This is why here I want on the top to import use reducer.
And this is just another hook.
But we need to do now before our component, we want to create an initial state for the whole component,
because Usereducer and use state are both used to create a local state for this specific component.
It is not for the whole react application.
We are talking here only about our component.
In our case it's a quiz component.
This is why here let's create a property initial state.
And this is an object.
And as you can see it is already easier because our state is always an object and we can create lots
of properties inside but don't have this problem like with your state where inside we typically store
separate values.
This is why inside we can create current question index and by default it will be zero.
Additionally, we want to store here our questions.
It is an array.
And if later we have other properties like answer or total we can store them here.
Additionally to that we are creating a reducer.
And what is a reducer?
This is a function where we define how our action must change our state.
And again this reducer is outside of our component, which is good because we want to write all our
business logic outside of the component.
And it helps in separation between our view and business logic.
This is why here our reducer accepts state and action and we just need to return here our state.
For now.
Our reducer does not do anything at all, it simply return state.
Insider quiz.
What do you want to do?
I want to use our usereducer and back.
I will get a state and the dispatch function and we are calling here our Usereducer.
And we must provide insight first of all, our reducer and secondly our initial state.
So again initial state is our initial object with all properties.
And reducer is a function.
How we plan to update our state.
Now inside our render I want to call state so we can check what we are getting inside.
As you can see here, inside console we are getting render and here is our object with default value.
This is current question index zero.
And our question is an empty array.
This is why directly here we can render this property from state dot current question index.
And this is totally fine.
This is just like a local property.
As you can see in browser our zero is being rendered correctly.
But now let's talk about dispatch.
What is dispatch at all.
This is how we trigger our actions.
But we don't have any actions at all.
Let's create it inside our reducer.
As you can see here, the second parameter is our action.
And our action typically looks like this.
It is just an object with type field and it is a string for example.
Next question.
And as you can see this is simply a string which defines what user did in our case.
Next question means that user clicked on the next question.
So this is our basic action.
It can have any string inside type but this is mandatory.
But additionally we can pack any properties that we want inside this action to provide some information.
This is why here what I want to write.
If our action dot type equals next question, then here I want to return updated state.
And in order to update our state, we are spreading our state that we have here inside this function.
And we want to update our current question index.
And it must equal state current question index plus one, which actually means our reducer is the place
where we are writing all our business logic.
We are writing here how that specific action changes our state.
Our component doesn't know anything about our business logic.
What our component knows is what state it must render and what action it must trigger.
This is why here we must trigger our action.
So we are writing here dispatch, and we are providing inside an object with type field.
And in our case it must be.
Next question why?
It is much better than simply calling a setter of your state.
Because in this case here we don't write any logic how we are changing our state.
We simply dispatch an action.
Our component doesn't really know what this action next question does, but here we can directly see
what happens.
User clicked on next action.
And then we are coming here inside reducer.
And when we are getting this action then we are changing the state.
Let's have a look in browser I'm reloading the page.
We are getting current question index zero.
It is rendered I'm clicking here.
We are getting one.
So it works exactly like previously.
But it was rendered.
And now here inside our state we are getting current question index one.
So again you state is totally fine.
But use reducer gives us more strict structure where defining initial state where defining reducer where
we will write if else conditions for every single action to define how our action changes our state.
And the last one here we are creating use reducer where we are getting state in dispatch, and we're
using state to render properties from the state.
And we're using dispatch to make some changes.
So dispatch actions.
And now here I want to clean it a little bit because this function is called test click.
And actually the single line we can write directly here.
So instead of test click we can just write here an anonymous function with word dispatch where inside
we are providing our type which is a next question.
And we can fully remove this test click.
We don't need it anymore.
And as you can see in browser, everything is working just like before.
So we can also remove this state current question index from here because it was just for testing.