大家好,我是小丞同学,一名大二的前端爱好者
这篇文章是学习 React-Redux 的学习笔记
非常感谢你的阅读,不对的地方欢迎指正
愿你忠于自己,热爱生活
引言
在前面我们学习了 Redux ,我们在写案例的时候,也发现了它存在着一些问题,例如组件无法状态无法公用,每一个状态组件都需要通过订阅来监视,状态更新会影响到全部组件更新,面对着这些问题,React 官方在 redux 基础上提出了 React-Redux 库
在前面的案例中,我们如果把 store 直接写在了 React 应用的顶层 props 中,各个子组件,就能访问到顶层 props
<顶层组件 store={store}> <App /> </顶层组件/>
这就类似于 React-Redux
容器组件和 UI 组件
1.所有的 UI 组件都需要有一个容器组件包裹
2.容器组件来负责和 Redux 打交道,可以随意使用 Redux 的API
3.UI 组件无任何 Redux API
4.容器组件用于处理逻辑,UI 组件只会负责渲染和交互,不处理逻辑
在我们的生产当中,我们可以直接将 UI 组件写在容器组件的代码文件当中,这样就无需多个文件
首先,我们在 src 目录下,创建一个 containers 文件夹,用于存放各种容器组件,在该文件夹内创建 Count 文件夹,即表示即将创建 Count 容器组件,再创建 index.jsx 编写代码
要实现容器组件和 UI 组件的连接,我们需要通过 connect 来实现
// 引入UI组件 import CountUI from '../../components/Count' // 引入 connect 连接UI组件 import {connect} from 'react-redux' // 建立连接 export default connect()(CountUI)
后面还会详细讲到
Provider
由于我们的状态可能会被很多组件使用,所以 React-Redux 给我们提供了一个 Provider 组件,可以全局注入 redux 中的 store ,只需要把 Provider 注册在根部组件即可
例如,当以下组件都需要使用 store 时,我们需要这么做,但是这样徒增了工作量,很不便利
<Count store={store}/> {/* 示例 */} <Demo1 store={store}/> <Demo1 store={store}/> <Demo1 store={store}/> <Demo1 store={store}/> <Demo1 store={store}/>
我们可以这么做:在 src 目录下的 index.js 文件中,引入 Provider ,直接用 Provider 标签包裹 App 组件,将 store 写在 Provider 中即可
ReactDOM.render( <Provider store={store}> <App /> </Provider>, document.getElementById("root") );
这样我们在 App.jsx 文件中,组件无需手写指定 store ,即可使用 store
connect
在前面我们看到的 react-redux 原理图时,我们会发现容器组件需要给 UI 组件传递状态和方法,并且是通过 props 来传递,看起来很简单。但是,我们会发现容器组件中似乎没有我们平常传递 props 的情形
这时候就需要继续研究一下容器组件中的唯一一个函数 connect
connect 方法是一个连接器,用于连接容器组件和 UI 组件,它第一次执行时,接收4个参数,这些参数都是可选的,它执行的执行的结果还是一个函数,第二次执行接收一个 UI 组件
第一次执行时的四个参数:mapStateToProps 、mapDispatchToProps 、mergeProps、options
mapStateToProps
const mapStateToProps = state => ({ count: state })
它接收 state 作为参数,并且返回一个对象,这个对象标识着 UI 组件的同名参数,
返回的对象中的 key 就作为传递给 UI 组件 props 的 key,value 就作为 props 的 value
如上面的代码,我们可以在 UI 组件中直接通过 props 来读取 count 值
<h1>当前求和为:{this.props.count}</h1>
这样我们就打通了 UI 组件和容器组件间的状态传递,那如何传递方法呢?
mapDispatchToProps
connect 接受的第二个参数是 mapDispatchToProps 它是用于建立 UI 组件的参数到 store.dispacth 方法的映射
我们可以把参数写成对象形式,在这里面定义 action 执行的方法,例如 jia 执行什么函数,jian 执行什么函数?
我们都可以在这个参数中定义,如下定义了几个方法对应的操作函数
{ jia: createIncrementAction, jian: createDecrementAction, jiaAsync: createIncrementAsyncAction }
写到这里其实 connect 已经比较完善了,但是你可以仔细想想 redux 的工作流程
似乎少了点什么,我们在这里调用了函数,创建了 action 对象,但是好像 store 并没有执行 dispatch ,那是不是断了呢?执行不了呢?
其实这里 react-redux 已经帮我们做了优化,当调用 actionCreator 的时候,会立即发送 action 给 store 而不用手动的 dispatch
·自动调用 dispatch
完整开发
首先我们在 containers 文件夹中,直接编写我们的容器组件,无需编写 UI 组件
先打 rcc 打出指定代码段,然后暴露出 connect 方法
import { connect } from 'react-redux'
从 action 文件中暴露创建 action 的方法
import {createIncrementAction} from '../../redux/count_action'
编写 UI 组件,简单写个 demo,绑定 props 和方法
return ( <div> <h2>当前求和为:{this.props.count}</h2> <button onClick={this.add}>点我加1</button> </div>);
调用 connect 包装暴露 UI 组件
export default connect( state => ({ count: state }),// 状态 { jia: createIncrementAction } // 方法)(Count);
第一次执行的参数就直接传递 state 和一个指定 action 的对象