Redux之action、store、reducer 使用
故事:其实自己天然的感觉react很难,所以一直没有入手去学习,同时感觉redux也是学习react里面比较难以理解的一部分(redux和react在技术上没有直接关系)
redux的核心概念
redux的核心概念就是store、action、reducer
store的创建
创建 store 文件夹, 接着在文件夹中创建 index.js
store/index
import { createStore } from 'redux'
import allReducer from '../reducers'
//创建了一个 store ,负责存储项目应用中的所有数据,传入两个参数
// 参数1: reducer 用来修改state
// 参数2(可选): [], 默认的state值,如果不传, 则为undefined
const store = createStore(
allReducer
);
export default store
复制代码
解释: createStore(reducer, [preloadedState], enhancer) 创建一个 Redux store 来以存放应用中所有的 state。 应用中应有且仅有一个 store。
store在这里代表的是数据模型,内部维护了一个state变量 store有两个核心方法,分别是getState、dispatch。前者用来获取store的状态(state),后者用来修改store的状态 ,store对象如下
{dispatch: ƒ, subscribe: ƒ, getState: ƒ, replaceReducer: ƒ, Symbol(observable): ƒ}
dispatch: ƒ dispatch(action)
getState: ƒ getState()
replaceReducer: ƒ replaceReducer(nextReducer)
subscribe: ƒ subscribe(listener)
Symbol(observable): ƒ observable()
__proto__: Object复制代码
通过 store.getState() 可以获取当前store的状态(state)
console.log(store.getState())
通过 store.dispatch(action) 来达到修改 state 的目的
注意: 在redux里,唯一能够修改state的方法,就是通过 store.dispatch(action)
store.dispatch({type: 'SETTHEME', themecolor: 'black'});
Provider
Provider在原应用组件上包裹一层,使原来整个应用成为Provider的子组件 接收Redux的store作为props,通过context对象传递给子孙组件上的connect 数据的获取是通过provider,将store里面的数据注入给组件。让顶级组件提供给他们的子孙组件调用
ReactDOM.render(
<Provider store={store}>
<BrowserRouter>
{routes }
</BrowserRouter>
</Provider>,
document.getElementById('app')
);复制代码
reducer的创建(reducer+actiocn+常量)
创建reducers文件夹,接着在文件夹中创建index.js
reducers/index
import { combineReducers } from 'redux';
import {theme} from './theme'
//合并reducers
export default combineReducers({
theme
});
复制代码
reducers/theme
/*常量*/
const SETTHEME = "SETTHEME"
// 初始化状态
let initThemeState = {
themecolor: "red"
}
//reducer reducer是一个纯函数。给定当前state树和要处理的action的函数,返回新的state树。
//reducer方法, 传入的参数有两个
//state: 当前的state
//action: 当前触发的行为, {type: 'xx'}
//返回值: 新的state
export function theme(state = initThemeState,action) {
switch (action.type) {
case "SETTHEME":
return {
...state,//把数组展开合并
themecolor:action.themecolor
}
default:
return state
}
}
// action 必须有一个type字段来标识这个行为的类型
export function setTheme(color) {
return {
type: SETTHEME,
themecolor: color
}
}
复制代码
reducer一个普通的函数,用来修改store的状态。传入两个参数 state、action 其中,state为当前的状态(可通过store.getState()获得),而action为当前触发的行为(通过store.dispatch(action)调用触发) reducer(state, action) 返回的值,就是store最新的state值
action对行为(如用户行为)的抽象,在redux里是一个普通的js对象 action必须有一个type字段来标识这个行为的类型
{ type: SETTHEME,themecolor: color }
mapStateToProps 与 mapDispatchToProps 与connect
import React, {PureComponent} from 'react'
import { connect } from 'react-redux'
import {BrowserRouter as Router, Route, Link} from 'react-router-dom'
class Product extends React.Component {
constructor(props){
super(props)
}
render() {
console.log(this.props)
return (
<div className="product-main" style={{backgroundColor:this.props.themecolor }}>
<div>这是产品页</div>
<button onClick={this.props.setTheme.bind(this,"pink")}>
设置主题 pink
</button >
<div style={{marginTop:20 + 'px'}}> <Link to="/user">账户中心</Link></div>
</div>
)
}
}
const mapStateToProps = (state) => {
return {
themecolor: state.theme.themecolor
}
}
const mapDispatchToProps = (dispatch) => {
return {
setTheme(corlor) {
const action = {
type: "SETTHEME",
themecolor:corlor
}
dispatch(action)
}
}
}
export default connect(mapStateToProps,mapDispatchToProps)(Product);
复制代码
react-redux 的另一个核心方法叫做connect 函数,,接受3个参数,一个 mapStateToProps 是把 Store 上的 state 映射为 props;另一个 mapDispatchToProps 则是把回调函数类型的 props 映射为派发 action 的动作,最后一个参数是连接的组件
connect 函数调用会产生一个『高阶组件』,一个高阶组件就是一个函数,它接受 React 组件为参数,返回一个新的 React 组件为结果。在上面的例子中,connect 产生的高阶组件产生了一个新的 React 组件 ,这个组件负责管理状态,而 Product组件是一个『傻瓜组件』,只负责渲染。
之前说 Provider 组件连接了 store , Provider 内部的组件有能力获取到 store ,是怎样获取的呢?就是通过 connect 这个方法获取到里面的数据的
如果需要对 store 的数据做修改,dispatch 是指的 store.dispatch ,可以通过 mapDispatchToProps 方法把 store.dispatch 挂载到props上,为什么呢? 因为想要改变 store 里的内容,就要调用 dispatch 方法, dispatch 方法被映射到了 props 上,所以就可以通过 this.props.dispatch 方法去调用了
<button onClick={this.props.setTheme.bind(this,"pink")}> 设置主题 pink </button >复制代码
@connect 装饰器
import React, {PureComponent} from "react"
import {BrowserRouter as Router, Route, Link} from 'react-router-dom'
import {connect} from 'react-redux'
import {setTheme} from "../../redux/reducers/theme"
@connect(state=> state.theme,{setTheme})
export default class User extends React.Component {
constructor() {
super()
}
render() {
return (
<div className="user-main" style={{backgroundColor:this.props.themecolor}}>
<div>这是账户中心</div>
<button
onClick={this.props.setTheme.bind(this,"blue")}>
设置主题 blue
</button>
<div> <Link to="/home">go首页</Link></div>
</div>
)
}
}复制代码
Redux 中核心的 API
createStore 可以帮助创建 store
store.dispatch 帮助派发 action , action 会传递给 store store.getState 这个方法可以帮助获取 store 里边所有的数据内容
store.subscrible 方法可以让让我们订阅 store 的改变,只要 store 发生改变, store.subscrible 这个函数接收的这个回调函数就会被执行