Visual LabINTERACTIVE LEARNING
框架原理第 4 / 7 章

React Redux

把 Store 接入组件树,并处理同步、异步与模块化 Reducer。

React组件Redux
进阶预计 58 分钟查看源文 ↗

react-redux

  • 把react和redux结合起来,封装提供高阶组件的函数,方便使用

使用步骤:

全局提供store

// index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './pages/App';
import { Provider } from 'react-redux'
import store from './store'

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
    <Provider store={store}>
        <App />
    </Provider>
);

在组件中使用,同步action

// component
// 在组件内使用,通过connect高阶函数,传递所需要的state和会触发的dispatch

//函数组件
import React from 'react'
import { connect } from 'react-redux'
import { addNumberAction, subNumberAction } from '../store/actionCreator'

export const About = (props) => {
    const { count, addCount, subCount } = props
    return (
        <div>
            <div> count: {count}</div>
            <button onClick={e => addCount(1)}>+</button>
            <button onClick={e => subCount(1)}>-</button>
        </div>
    )
}
const mapStateToProps = (state) => ({ count: state.count })
const mapDispatchToProps = (dispatch) => ({
    addCount: (num) => dispatch(addNumberAction(num)),
    subCount: (num) => dispatch(subNumberAction(num))
})
export default connect(mapStateToProps, mapDispatchToProps)(About)

// 类组件
import React, { Component } from 'react'
import { connect } from 'react-redux'
import { addNumberAction, subNumberAction } from '../store/actionCreator'
export class Home extends Component {
    render() {
        const { count, addCount, subCount } = this.props
        return (
            <div>
                <div>Home</div>
                <div> count: {count}</div>
                <button onClick={e => addCount(1)}>+</button>
                <button onClick={e => subCount(1)}>-</button>
            </div>
        )
    }
}
const mapStateToProps = (state) => ({ count: state.count })
const mapDispatchToProps = (dispatch) => ({
    addCount: (num) => dispatch(addNumberAction(num)),
    subCount: (num) => dispatch(subNumberAction(num))
})
export default connect(mapStateToProps, mapDispatchToProps)(Home)

异步action

需要使用中间件增强,redux-thunk

// 安装中间件 redux-thunk,并使用
import { createStore, applyMiddleware } from "redux";
import reducer from "./reducer";
import { thunk } from "redux-thunk";

export const store = createStore(
    reducer, applyMiddleware(thunk)
)

export default store
  1. 编写异步action
//这个action返回一个函数,返回的这个函数会被中间件调用,并传入两个参数,dispatch和getState
//当异步的结果获取的时候,再次dispatch真正的数据过去,这个action还是正常的可以传入参数
export const fetchDataAction = (num) => {
    //返回的这个函数会被thunk中间件调用,传递一个dispatch和getState函数进来
    return (dispatch, getState) => {
        axios.get('').then(res => {
            const data = res.data.count
            dispatch(addNumberAction(data))
        })
    }
}
  1. 组件中派发action
import React, { Component } from 'react'
import { connect } from 'react-redux'
import { addNumberAction, fetchDataAction, subNumberAction } from '../store/actionCreator'
export class Home extends Component {
    render() {
        const { count, addCount, subCount,fetchCount } = this.props
        return (
            <div>
                <div>Home</div>
                <div> count: {count}</div>
                <button onClick={e => addCount(1)}>+</button>
                <button onClick={e => subCount(1)}>-</button>
                <button onClick={e => fetchCount(1)}>fetchCount</button>
            </div>
        )
    }
}

const mapStateToProps = (state) => ({ count: state.count })

const mapDispatchToProps = (dispatch) => ({
    addCount: (num) => dispatch(addNumberAction(num)),
    subCount: (num) => dispatch(subNumberAction(num)),
    fetchCount: (num) => dispatch(fetchDataAction(num))
})

export default connect(mapStateToProps, mapDispatchToProps)(Home)

模块的拆分 - 多个reducer

// 在store创建的时候,使用一个combineReducers去合并不同的reducer,
// 就可以把不同的reducer和action分离出去
// 使用时也需要多家一层key去去取到对应的state
import { createStore, applyMiddleware,combineReducers } from "redux";
import homeReducer from "./reducer";
import { thunk } from "redux-thunk";

const reducer =  combineReducers({
 home:homeReducer
})

export const store = createStore(
    reducer, applyMiddleware(thunk)
)

export default createAsyncThunkstore