For Redux Toolkit, click here
Redux extracts the shared state from the components tree and puts it into a centralized location.
React and Redux expect that all state updates are done immutably
type
field.type
should be a descriptive name, follows the "domain/eventName"
pattern, like "todos/todoAdded"
.Example:
const addTodoAction = {
type: 'todos/todoAdded',
payload: 'Buy milk',
};
Redux actions and state should only contain plain JS values like objects, arrays, and primitives. Don't put class instances, functions, Date/Map/Set instances, or other non-serializable values into Redux!.
A function returns an action object:
const addTodo = (text) => {
return {
type: 'todos/todoAdded',
payload: text,
};
};
state
and an action
, and returns the
new state: (state, action) => newState
.state
and action
arguments.state
.Example:
const initialState = { value: 0 };
function counterReducer(state = initialState, action) {
// Check to see if the reducer cares about this action
if (action.type === 'counter/increment') {
// If so, make a copy of `state`
return {
...state,
// and update the copy with the new value
value: state.value + 1,
};
}
// otherwise return the existing state unchanged
return state;
}
It is called reducer because it works similar to Array.reduce
, like in this
example:
const actions = [
{ type: 'counter/increment' },
{ type: 'counter/increment' },
{ type: 'counter/increment' },
];
const initialState = { value: 0 };
type State = typeof initialState;
type Action = (typeof actions)[0];
const counterReducer = (state: State, action: Action) => {
if (action.type === 'counter/increment') {
return {
value: state.value + 1,
};
}
return state;
};
const finalResult = actions.reduce(counterReducer, initialState);
console.log(finalResult);
This is how we call all of the slice reducers by hand:
function rootReducer(state = {}, action) {
return {
users: usersReducer(state.users, action),
posts: postsReducer(state.posts, action),
comments: commentsReducer(state.comments, action),
};
}
But Redux has a function called combineReducers
:
const rootReducer = combineReducers({
users: usersReducer,
posts: postsReducer,
comments: commentsReducer,
});
While using Redux Toolkit we can also pass a reducer function directly as the
reducer
argument:
const store = configureStore({
reducer: rootReducer,
});
It is where the state lives.
This example blow shows how to use configureStore
from Redux Toolkit, by by
passing a reducer
. We can use store.getState()
to get the current state
value:
import { configureStore } from '@reduxjs/toolkit';
const store = configureStore({ reducer: counterReducer });
console.log(store.getState());
// {value: 0}
action
as the parameter.state
.So we can say dispatch
triggers an event, then reducer
handles the state
updating.
Example:
store.dispatch({ type: 'counter/increment' });
console.log(store.getState());
Or call an action creator to dispatch the action:
const increment = () => {
return {
type: 'counter/increment',
};
};
store.dispatch(increment());
console.log(store.getState());
A functions that extracts a piece of information from state
, so you do not
have to repeat the same logic again and again in your application.
const selectCounterValue = (state) => state.value;
const currentValue = selectCounterValue(store.getState());
console.log(currentValue);
It is a "one-way data flow".
state
.state
.action
to the Redux store.state
is updated.