刚开始接触 React 时就听过 Redux ,虽然 Redux 对 React 并不是必要的,但在 React 生态中也是个使用比较频繁的组件,相信也值得花时间好好了解。
在使用后,也能感受到 Redux 对项目带来的好处:
- 让组件管理 state 更方便,且确保整个项目的数据都来自同一个地方。
- 开发时能让界面及数据端分离,有关界面的就修改 React 的 component,数据的部分就完全交给 Redux,每个人各司其职、分工合作。
既然 React 和 Redux 两者间可以这么相处融洽,那不如就开始试试吧!
Redux 基本用法
在讲解两者如何配合前,还是得先了解 Redux 的运作模式。
创建 Reducer
Reducer 在 Redux 中是用来保管 state ,以及在接收到不同的 action 指令时该对 state 做什么动作的函数。
首先要为该 Reducer 设计它所管理的 state 结构:
const initState = {
name: 'Jack',
}
虽然在 Reducer 中也可以改变 state 的结构,但在 initState 中将数据结构清楚列出,还能让接手的人或是两个礼拜后的自己,一看就能知道这个 Reducer 保管了哪些数据。
现在有了初始数据,就可以使用它建立一个 Reducer :
const reducer = (state = initState, action) => {
switch (action.type){
default:
return state
}
}
每一个 Reducer 都会有两个参数,第一个参数会将初始的数据状态 initState 交由 Reducer 保管,第二个参数会传入现在 reducer 要对 state 做什么动作的指令及额外的参数,这些在后几篇会再讲解,所以在还没有任何 action 指令描述的 Reducer 内,默认返回了它所保管的 state ,在这里就是上方的 initState 。
创建 store
创建 Reducer 后,还得将它交由 store , store 的工作就是在应用程序中负责整合所有的 Reducer 。
创建前,得先从 redux 中 import 进负责创建 store 的函数 createStore ,并将 Reducer 传入以创建一个 store :
import { createStore } from 'redux'
const store = createStore(reducer)
//可使用 store 的内置函数 getState() 确认目前 store 内所保管的数据console.log(store.getState()) // {name: 'Jack'}
需要注意的是,每个项目都应该只能有一个 store 存在,若是有许多不同类型的数据,则是以 Reducer 区分,最后将多个 Reducer 打包成一个后,再创建 store ,这部分的使用方法,在日后的文章也会解说。
store 产生后, Redux 的前置准备部分就告一段落,接下来说明 React 的 component 该如何从 Redux 的 store 中取到数据。
React-Redux 登场
在React-Redux的架构中,我们需要一种方法来告诉React组件它应该从Redux store中获取哪些数据。这就像是在超市购物时,你会有一个购物清单,上面列出了你需要购买的所有商品。在这个比喻中,数据映射函数就相当于你的购物清单。
- 创建购物清单:首先,你需要创建一个购物清单,这个清单是一个函数,它定义了你需要从
Redux store中获取哪些数据项。在这个函数中,你会指定每项数据的名称和它在store中的位置。 - 连接超市和购物车:然后,你将这个购物清单与超市(
Redux store)和购物车(React组件)连接起来。这样,当你需要数据时,可以根据购物清单上的信息,从store中取出对应的数据。 - 填充购物车:最后,通过一个连接器(
React-Redux的connect函数),将购物清单上的数据项填充到购物车中,这样你的组件就可以使用这些数据来渲染界面了。
React 需通过几个步骤才能将 Redux 所保管的数据流向 component 。首先需要定义要从 store 中取得的数据,并将 component 与该数据源连接起来,之后再利用 Provider 将 store 根据组件中使用到的参数将对应数据流进 component 中。以下开始实现这些步骤:
定义数据
const mapStateToProps = state => ({
name: state.name
})
上方创建一个函数 mapStateToProps ,并在该函数内部定义需要哪些数据,它有个参数 state ,在连接时 Redux 会将 store 传进这个位置,因此上方指定了 store 中保管的 name 数据,并以 name 为 key 从 props 流进 component 中。
创建组件
import React from 'react'
class ConnectTitle extends React.Component {
render(){
return <h1>Hello!{this.props.name}</h1>
}
}
因为待会会与 mapStateToProp 进行连接,所以在组件名称前个人多注记了 Connect ,代表该 component 内含有从 store 中取的数据,而上方的 {this.props.name} 正是数据定义时指定的名称也就是 name 。
连接 component 与 mapStateToProps
在这个步骤前得先从 react-redux 中 import 进 connect ,再进行连接:
import { connect } from 'react-redux'
const Title = connect(mapStateToProps)(ConnectTitle)
通过 connect 分别将 mapStateToProps 与 ConnectTitle 送进处理,会得到一个新的 component ,在上方使用 Title 接收结果。
设置 Provider
Provider 是 react-redux 中的组件,它会接收上方在 Redux 中创建的 store ,并根据和 component 绑在一起的mapStateToProps 上要求的数据从 store 中取出,再通过 props 流向 component 。
import { connect, Provider } from 'react-redux'
import ReactDOM from 'react-dom'
ReactDOM.render(<Provider store={store}>
<Title />
</Provider>,
document.getElementById('root'))
上方的 Provider 在最外层,并为他指定了 store 。
注意!不论是多么大的项目, Provider 永远都在最外层,也永远都只有一个,为了保持数据来源都是从 Provider 流进内部的 component ,这也是为什么每个项目中 store 应该都只能有一个。
接着运行应用程序,确认最后输出的结果:
本文是关于React及Redux最基本使用方式,笔者刚学的时候真的觉得很困难,也有许多观念一直理不清楚,包括上面提到的store为什么只能有一个,不过好在三番两次的实际操作后,不仅更了解,而且像开头说的,体会到使用Redux的好处后,对他就更爱不释手,希望本篇文章能够带给和当初的我一样,为学习Redux困扰的大家。