React foundation consolidation (35) - ReduxToolKit (RTK)
1. Introduction to RTK
-
Redux Tool Kit (RTK) is the officially recommended way to write Redux logic, aiming to become the standard way of writing Redux logic, thus solving the problems mentioned above.
-
The core APIs of RTK mainly include the following:
-
configureStore: Wraps createStore to provide simplified configuration options and good defaults. It automatically composes your slice reducers, adds any Redux middleware you provide, redux-thunk is included by default, and enables the Redux DevTools Extension.
parameter describe reducer Pass the reducers in the slice into an object here middleware incoming middleware devTools Whether to configure devTools tools, the default is true -
createSlice: Accepts the object of the reducer function, the slice name and the initial state value, and automatically generates a slice reducer with corresponding actions.
parameter describe name The ranking of the slice marked by the user initialState initialization value reducers reducer function, object type, can add multiple createSlice The return value is an object containing all actions -
createAsyncThunk: Accepts an action type string and a function that returns a promise, and generates a pending/fulfilled/rejected thunk that dispatches the action type based on the promise.
-
2. Simple use of RTK
-
Install toolkit and react-redux
npm install @reduxjs/toolkit react-redux
-
Use createSlice to build store slices (store/features/counter.js)
import { createSlice } from "@reduxjs/toolkit"; // createSlice(用户标记slice的名称, ) const counterSlice = createSlice({ name: "counter", initialState: { counter: 989, }, reducers: { addNumber(state, { payload}) { console.log("add number", payload); state.counter = state.counter + payload; }, subNumber(state, { payload}) { console.log("sub number", payload); state.counter = state.counter - payload; }, }, }); export const { addNumber, subNumber } = counterSlice.actions; export default counterSlice.reducer;
-
use configureStore place store (store/index.js)
import { configureStore } from "@reduxjs/toolkit"; import counterReducer from "./features/counter"; const store = configureStore({ reducer: { counter: counterReducer, }, }); export default store;
-
Using react-redux, inject the store into index.js according to the usual practice
import React from "react"; import ReactDOM from "react-dom/client"; import { Provider } from "react-redux"; import App from "./App"; import store from "./store"; const root = ReactDOM.createRoot(document.getElementById("root")); root.render( // <React.StrictMode> <Provider store={ store}> <App /> </Provider> // </React.StrictMode> );
-
Using react-redux, according to the usual practice, connect through connect in the page file that needs to use store and dispatch operations
// Home.jsx import React, { PureComponent } from "react"; import { connect } from "react-redux"; import { addNumber } from "../store/features/counter"; export class Home extends PureComponent { addNumber(num) { this.props.addNumber(num); } render() { const { counter } = this.props; return ( <div> home:{ counter} <button onClick={ (e) => this.addNumber(5)}>+5</button> <button onClick={ (e) => this.addNumber(8)}>+8</button> <button onClick={ (e) => this.addNumber(18)}>+18</button> </div> ); } } const mapStateToProps = (state) => ({ counter: state.counter.counter, }); const mapDispatchToProps = (dispatch) => ({ addNumber(num) { dispatch(addNumber(num)); }, }); export default connect(mapStateToProps, mapDispatchToProps)(Home);
// Profile.jsx import React, { PureComponent } from "react"; import { connect } from "react-redux"; import { subNumber } from "../store/features/counter"; export class Profile extends PureComponent { subNumber(num) { this.props.subNumber(num); } render() { const { counter } = this.props; return ( <div> profile:{ counter} <button onClick={ (e) => this.subNumber(5)}>-5</button> <button onClick={ (e) => this.subNumber(8)}>-8</button> </div> ); } } const mapStateToProps = (state) => ({ counter: state.counter.counter, }); const mapDispatchToProps = (dispatch) => ({ subNumber(num) { dispatch(subNumber(num)); }, }); export default connect(mapStateToProps, mapDispatchToProps)(Profile);
-
Import the interface into App.jsx
import React, { PureComponent } from "react"; import { connect } from "react-redux"; import Home from "./pages/Home"; import Profile from "./pages/Profile"; import "./style.css"; export class App extends PureComponent { render() { const { counter } = this.props; return ( <div> <h2>App Counter: { counter}</h2> <div className="pages"> <Home /> <Profile /> </div> </div> ); } } const mapStateToProps = (state) => ({ counter: state.counter.counter }); export default connect(mapStateToProps)(App);
-
Viewing the running results, it is consistent with the effect of using react-redux alone before, but it is simplified at the code level