1. React-redux Hooks API
Hooks provide a lot of useful apis, and many people even think that Hooks’ useReducer API is a good substitute for Redux. The react-Redux (7.1) also introduces an Hooks style Api.
1.1 Disadvantages of useState
UseState and useReducer are the most commonly used apis in Hooks, which are suitable for simple state management, but both have unmet requirements
UseState can update status in the simplest possible way, but the logic for status updates (such as the addition and subtraction in the above example) is scattered in the business code and cannot be independently reused or tested.
import React, { useState } from "react";
const ComponentUseState = () = > {
const [num, setNum] = useState(0);
return (
<div>
<h2>Using useState</h2>
Number: {num}
<button onClick={()= > setNum(num + 1)}>+</button>
<button onClick={()= > setNum(num - 1)}>-</button>
</div>
);
};
Copy the code
1.2 [Evolution] useReducer solves problems that useState cannot solve
Using useReducer can solve the problems that useState cannot solve above.
As you can see, useReducer’s logic is separate from the UI and can be reused independently. Reducer is a simple Js method, so we can test the reducer separately, or even debug it in Chrome
import React, { useReducer } from 'react'
const initialState = {num: 0};
const reducer = (state, action) = > {
switch(action.type) {
case 'decrement':
return{... state,num: state.num - 1}
case 'increment':
return{... state,num: state.num + 1}
default:
returnstate; }}const ComponentUseReducer = () = > {
const [state, dispatch] = useReducer(reducer, initialState)
const { num } = state
return (
<div>
<h2>Using useReducer</h2>
Number: {num}
<button onClick={()= > dispatch({type: 'increment'})}>+</button>
<button onClick={()= > dispatch({type: 'decrement'})}>-</button>
</div>
);
};
export default ComponentUseReducer;
Copy the code
1.2.1 useReducer cannot be shared across component states like Redux
In practice, the reducer should have separate files. In this example, the reducer is grouped together for simplicity.
UseReducer, while a good separation of logic and UI, does not share state across components like Redux, such as child components cannot easily access num
1.3 useSelector, useDispatch
As mentioned above, Hooks are still no substitute for Redux, especially when it comes to state sharing. Fortunately, after react-Redux 7.1, hooksapis such as useSelector and useDispatch can also be used instead of Connect, reducing the template code.
import React from "react";
import { createStore } from "redux";
import { Provider, useSelector, useDispatch } from "react-redux";
const initialState = { num: 0 };
const reducer = (state, action) = > {
switch (action.type) {
case "decrement":
return { ...state, num: state.num - 1 };
case "increment":
return { ...state, num: state.num + 1 };
default:
returnstate; }};const store = createStore(reducer, initialState);
const ComponentUseReactRedux = () = > {
return (
<div>
<h2>ComponentUseReactRedux</h2>
<Provider store={store}>
<ChildComponentUseReactRedux />
</Provider>
</div>)}const ChildComponentUseReactRedux = () = > {
const num = useSelector(state= > state.num);
const dispatch = useDispatch();
return (
<div>
<h3>Using useSelector, useDispatch</h3>
Number: {num}
<button onClick={()= > dispatch({ type: "increment" })}>+</button>
<button onClick={()= > dispatch({ type: "decrement" })}>-</button>
</div>
);
};
export default ComponentUseReactRedux;
Copy the code
1.3.1 Code Description:
createStore
The createStore is used to store the state
const store = createStore(reducer, initialState);
Copy the code
The store is then exposed to the child components through the Provider, and the state is shared between the parent and child components through the store
<Provider store={store}>
<ChildComponentUseReactRedux />
</Provider>
Copy the code
useSelector
Child components can access name through useSelector
const num = useSelector(state= > state.num);
Copy the code
Of course, you can also come up with a selector function for easy substitution and reuse, as follows
const selector = state= > {
return state.num;
}
const num = useSelector(selector);
Copy the code
useDispatch
You can obtain the dispatch through useDispatch
const dispatch = useDispatch()
Copy the code
Even more subcomponents can share state
const ComponentUseReactRedux = () = > {
return (
<div>
<h2>ComponentUseReactRedux</h2>
<Provider store={store}>
<ChildComponentUseReactRedux />
<ChildComponentUseReactRedux />
</Provider>
</div>)}Copy the code
Summary – Evolutionary flow
- 【useState】-> 【useReducer】-> 【useSelector, useDispatch】
- There is no substitute relationship between Hooks and Redux. Therefore, it is necessary to combine them better.