美文网首页
React-Redux 使用

React-Redux 使用

作者: 爱吃豆包 | 来源:发表于2020-03-12 23:37 被阅读0次

目前使用版本

"redux": "^4.0.5"
"react-redux": "^7.2.0",

建议先了解 Redux 的使用!Redux使用(纯Redux使用)

React-Redux 是 Redux 和 React 的绑定库!

为什么要使用这个 React-Redux 库:

在之前的文章Redux使用(纯Redux使用)里面使用的是 store.subscribe()的方式进行监听了store 的里面的state的变化!虽说这样做也可以,但是会有其他的性能问题,比如:渲染页面重复的问题,你可能通过生命周期函数shouldComponentUpdate可以处理,但是这样太繁琐,特别是组件越来越复杂之后!
React-Redux 这个库在官方说明中是有性能优化的!特别是提供了一种connect()方式来进行包装组件,这种方式就是我们在做 容器化组件展示组件 进行 分离的时候的 容器化组件

  • 容器组件:处理 props 或者 state
  • 展示组件:只负责展示界面

比如说:你把网路请求放到 容器组件 中,然后在 容器组件 里面把数据组装好,然后传递给 展示组件 直接渲染页面展示!
可以看看我之前的文章:React高阶组件

核心API

  • <Provider store={store}>...</Provider>:这个组件是重点,要在你的根目录下的index.js文件把根组件进行包裹
import TodoList from './list/TodoList';
import { Provider } from 'react-redux'
import store from './redux/store/index'
========================= 省略一大波代码 ======

// 重点这里
<Provider store={store}>
      <TodoList />
</Provider>, 
  • connect(....) :连接函数,把组件和redux进行关联!这个是重点函数,这里可以把 statedispatch 传递进去!

connect(....) 有几个参数很关键(重点关注两个):

  • mapStateToProps(state, [ownProps]):如果定义该参数,组件将会监听 Redux store 的变化。任何时候,只要 Redux store 发生改变,mapStateToProps 函数就会被调用。该回调函数必须返回一个纯对象,这个对象会与组件的 props 合并!

这个函数,就是监听 Redux store 的数据变化的!!

/**
 * 把 store 里面 state 状态,附加到 props 上
 * 这里的参数两个参数,connect()自动赋值
 * @param {*} state store的全局状态,connect()自动赋值
 * @param {*} ownProps 组件本身自己带的props, connect()自动赋值
 */
const mapStateToProps = (state, ownProps) => {

    /**
     * 这里可以只拿取你需要的 state 里面的数据,这样可以节省性能开销
     * 比如我这里只要 state 里面的 list
     * 然后组件里面可以通过 props 获取 list 的值
     */

    return { list: state.list }
}
  • mapDispatchToProps(dispatch, [ownProps]):如果传递的是一个对象,那么每个定义在该对象的函数都将被当作 Redux action creator,对象所定义的方法名将作为属性名;每个方法将返回一个新的函数,函数中dispatch方法会将 action creator 的返回值作为参数执行。这些属性会被合并到组件的 props 中。

(1):这个函数,就是用来执行dispatch的,就是说可以把这个组件中所有的dispatch操作从组件里面都提取出来统一管理!
(2):如果不定义 mapDispatchToProps ,那么默认把所有的dispatch都传递到组件中,那么你可以在组件中直接操作dispatch

/**
 * 把里面定义的函数附加到 props 上
 * 组件可以通过 props.onTodoClick(id) 进行调用
 */
const mapDispatchToProps = (dispatch, ownProps) => {
  return {
    /**
     * 可以定义多个函数
     * 组件可以通过 props.onTodoClick(id) 进行调用
     **/
    onTodoClick: id => {
      dispatch(toggleTodo(id))
    }
  }
}

开始使用 React-Redux

安装依赖

// redux 相关
yarn add redux react-redux redux-devtools-extension --save

这里安装了三个库:reduxreact-reduxredux-devtools-extension

  • redux 是 Redux 的原生核心库
  • react-redux 是 React 和 Redux 的绑定库(有额外的性能优化)
  • redux-devtools-extension 是一个开发组工具库可以在浏览器上看到 store 里面的 state 的变化,方便调试!

这里例子使用了 Antd 组件库!

先定义 action

// redux/action/list/index.js

/**
 * Action 类型
 *      事件类型
 */
export const type = {
    ADD_LIST: 'ADD_LIST'
}

/**
 * 添加 List
 * @description 也就是获取添加 List 操作类型, 以及携带的数据
 * @param {*} data 携带的数据
 */
export function addList(data) {
    return {
        type: type.ADD_LIST,
        data
    }
}

定义 reducer

// redux/reducer/list/index.js

import { type } from '../../action/list'

 // 数据仓库
 const initialState = {
    data: [
        "这是第一行",
        "这是第二行",
        "这是第三行"
    ],
 }

 /**
  *  list 数据处理
  * @param {*} state 
  * @param {*} action 
  */
export default function list(state = initialState, action) {
    switch (action.type) {
        case type.ADD_LIST:

            /**
             * 处理完一些里操作后,返回一个新的 state
             */

            // 把新的值,添加进 state
            const newData = state.data.concat(action.data)

            return {
                ...state,
                data: newData
            }
        default:
            return { ...state }
    }
}

集中我们定义了一系列的 reducer 的函数

// redux/reducer/index.js

/**
 * Reducer 数据处理
 */
import { combineReducers } from 'redux'
import list from './list'

/**
 * 把多个 reducer 进行合并成一个
 */
export default combineReducers({

    /**
     * 写入一系列的 reducer
     */

    list
})

创建 store

/**
 * 创建数据源  store
 */
import { createStore } from 'redux'
import reducer from '../reducer'
import { composeWithDevTools }  from 'redux-devtools-extension'

// 创建 store
// reducer 一定要是一个函数
// composeWithDevTools() 一定要写成这样,不能写成 composeWithDevTools
const store = createStore(reducer, composeWithDevTools())
export default store

创建 TodoList.js

import React, { Component } from 'react'
import { Input, Button, List } from 'antd';
import { connect } from 'react-redux'
import { addList } from '../redux/action/list'

/**
 * TodoList 一个列表
 */
class TodoList extends Component {

    constructor(props) {
        super(props)
        
        this.inpVal = React.createRef();

        this.state = {
            // data: [
            //     "这是第一行",
            //     "这是第二行",
            //     "这是第三行"
            // ],
            data: []
        }

    }

    componentDidMount() {
        this.setState({ data: this.props.list.data || [] })
    }

    componentDidUpdate(prevProps) {
        // 典型用法(不要忘记比较 props)
        if (this.props.list.data !== prevProps.list.data) {
            this.setState({ data: this.props.list.data || [] })
        }
    }

    addData() {
        const { dispatch } = this.props
        const inputValue = this.inpVal.current.state.value
        console.log('当前值:', inputValue)
        if (inputValue === undefined) {
            return
        }
        // this.setState({ data: this.state.data.concat(inputValue) })
        // 更新store
        dispatch(addList(inputValue))
        this.inpVal.current.state.value = undefined
    }

    render() {
        // console.log('this.props: ', this.props)
        return (
            <>
                <div style={{ margin: '10px' }}>
                    <div>
                        <Input ref={ this.inpVal } placeholder="请输入内容" style={{ width: '200px' }}/>
                        <Button type="primary" style={{ marginLeft: '10px' }} onClick={this.addData.bind(this)}>确认</Button>
                        <List
                            style={{ marginTop: '10px', width: '200px' }}
                            bordered
                            dataSource={this.state.data}
                            renderItem={(item, index) => (
                                <List.Item key={index}>
                                    {item}
                                </List.Item>
                            )}
                        />
                    </div>
                </div>
            </>
        )
    }
}

/**
 * 把 store 里面 state 状态,附加到 props 上
 * @param {*} state store的全局状态
 * @param {*} ownProps 组件本身自己带的props
 */
const mapStateToProps = (state, ownProps) => {

    /**
     * 这里可以只拿取你需要的 state 里面的数据,这样可以节省性能开销
     * 比如我这里只要 state 里面的 list
     * 然后组件里面可以通过 props 获取 list 的值
     */

    return { list: state.list }
}

/**
 * connect 是一个容器
 * 把 原有的组件进行装饰一下(装饰者模式)
 */
export default connect(mapStateToProps)(TodoList)


修改根目录下 index.js 文件

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import TodoList from './list/TodoList';
import { Provider } from 'react-redux'
import store from './redux/store/index'
import * as serviceWorker from './serviceWorker';

ReactDOM.render(
    <Provider store={store}>
        <TodoList />
    </Provider>, 
    document.getElementById('root')
);

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();

结果:

结果截图

题外话:

结合实际项目开发的时候,redux 肯定是分为多个子模块的。可以把 actionreducer 拆分成多个!那么 reducer 拆分后,在定义一个统一的 reducer 文件进行合并!通过 redux 提供的 combineReducers 函数可以把多个子reducer进行合并!

示例图

代码:https://github.com/weiximei/redux-demo
ps: 平常码云用的最多!

相关文章

  • react-redux

    使用react-redux,可以更方便的使用redux开发 先install react-redux使用react...

  • 20.redux使用

    react-redux 使用一个react-redux 的库使得redux的使用更简洁,它提供了provider和...

  • react-redux

    redux 全局状态管理 react-redux 优化模块 优化redux的使用过程 通过react-redux ...

  • React-Redux(一):react-redux使用

    react-redux使用步骤如下添加react-redux库 2.创建store 在祖先元素引入provider...

  • 手写connect

    使用react-redux中的 使用的时候 r...

  • 一个完整小巧的Redux全家桶项目

    OneArticle: 使用React-Native开发,使用Redux,React-Redux,Redux-Pe...

  • react-redux框架之connect()与Provider

    react-redux 在react-redux 框架中,给我提供了两个常用的API来配合Redux框架的使用,其...

  • react依赖注入之mapStateToProps&&mapDi

    在react-redux开发中每个模块有自己的state用来统一管理视图数据。在使用react-redux之后,可...

  • React-Redux 使用

    目前使用版本 建议先了解 Redux 的使用!Redux使用(纯Redux使用) React-Redux 是 Re...

  • redux

    单独使用redux redux是核心库 与react配合使用redux 安装react-redux react-r...

网友评论

      本文标题:React-Redux 使用

      本文链接:https://www.haomeiwen.com/subject/wwsgjhtx.html