redux
介绍
Redux是 JavaScript 状态容器,提供可预测化的状态管理。
在 react 中可以用来集中式管理 react 应用中多个组件共享的状态。
使用场景
-
某个组件的状态,需要让其他组件可以随时拿到(共享)。
-
当一个组件需要改变另一个组件的状态(通信)。
使用
npm install --save redux
使用步骤
1、创建 reducer.js 文件,定义 reducer 函数 ,建立初始状态。
js
// reducer.js
// 初始化的状态
const defaultState = {
num: 30,
}
// reducer 函数传入了两个参数 state、action
/*
state:状态数据
action:为一个动作对象,有着两个属性 type 和 data
type:标识属性, 值为字符串, 唯一, 必要属性
data:数据属性, 值类型任意, 可选属性
例子:{ type: 'add_number', data: 5}
*/
// reducer 用于初始化状态、加工状态
const reducer = (
state = defaultState,
action
) => {
state = JSON.parse(JSON.stringify(state))
switch(action.type) {
case "addOne":
state.num++;
break;
case "addNum":
state.num += action.value;
break;
default:
break;
}
return state;
}
export default reducer;
2、创建 index.js 文件,导入 redux 的 legacy_createStore 函数。引入 reducer.js 文件,将其中的 reducer 函数传入到 legacy_createStore 生成 store 对象,并暴露出来。
js
// index.js
// import { createStore } from "redux"; // 现已弃用
// legacy_createStore 用于创建 redux 中最为核心的 store 对象
import { legacy_createStore } from "redux";
import reducer from "./reducer"
const store = legacy_createStore(reducer);
export default store
3、在组件中导入 store 并使用。
js
// App.js
import React, { Component } from 'react'
import store from './store';
export default class App extends Component {
componentDidMount() {
store.subscribe(() => {
// 借用 state 来调用 render 更新页面。
this.setState({});
})
}
addOne = ()=> {
store.dispatch({
type: 'addOne',
data: 5
})
}
render() {
return (
<div className="App">
<div>{store.getState().num}</div>
<button onClick={this.addOne}>+ 1</button>
</div>
);
}
}
此时我们打印 store 可以看到这么一个对象:
- getState() 获取 state 状态
- dispatch(action) 修改 store 中的 state 值的唯一途径就是通过调用 dispatch 方法匹配 dispatch 传入的 type 字段从而执行对应匹配 reducer 函数中的逻辑修改 state
- subscribe(listener) 注册监听器,监听状态里所有数据的变化
- replaceReducer(reducer) 接受一个 reducer 作为参数,它会替换 store 当前用来计算 state 的 reducer
- observable 这个函数通常情况下不会使用, 是为了配置具有 observable/reactive 特性的三方库来使用的, 其返回一个对象, 对象中包括订阅方法, 该类似 subscribe 方法
action 对象文件
可以专门创建一个 action 文件,来放置 action 对象。
js
// store_action.js
const createAddAction = data => ({ type: 'addNum', data })
export { createAddAction }
使用
js
store.dispatch(createAddAction(30))
异步 action
有时候执行的操作涉及接口、定时等异步任务,延时来修改状态。可以由 action 待执行异步任务。
由于 dispatch 传递的值是一个函数,本身是只接受对象值, 所以需要一个中间件来转换,利用 npm i redux-thunk
来解决这个问题。
js
// store/index.js
// applyMiddleware 用于执行中间件
import { legacy_createStore, applyMiddleware } from "redux";
import reducer from "./reducer"
// 用于支持异步 action
import thunk from "redux-thunk"
const store = legacy_createStore(reducer, applyMiddleware(thunk));
export default store
action 对象文件
js
// store_action.js
const createAddAction = data => ({ type: 'addNum', data })
const createAddActionAsync = (data, time) => {
// store 根据接收的参数,接受的是函数,根据函数的形参去调用相应的dispatch
return (dispatch) =>{
setTimeout(()=> {
dispatch(createAddAction(data))
}, time)
}
}
export { createAddAction, createAddActionAsync }
使用
js
import { createAddActionAsync } from '../store/store_action'
addNum = ()=>{
store.dispatch(createAddActionAsync(30))
}
react-redux
react-redux 是 react 专用的插件库,用来简化 react 应用中使用 redux 的操作。
npm install --save react-redux
组件例子
react-redux 将组件分为 容器组件 和 UI组件。 -容器组件 负责管理数据和业务逻辑 -UI组件 负责视图呈现,通过 props 接收数据
App.js 用来传递 store:
js
import React, { Component } from 'react'
import Container from './containers/index';
import store from './store';
export default class App extends Component {
render() {
return (
<div className="App">
123
// 给容器组件传递 store
<Container store={store} />
</div>
);
}
}
容器组件 containers.js 可以获取到 App.js 传递 store:
js
// containers.js
import uiCom from './components/uiComponents'
// 引入 connect 用于连接 UI组件与 redux
import { connect } from 'react-redux'
// 引入 action ,集中管理 action
import { createAddAction, createJianAction } from '../store/store_action'
// state 相当于 store 状态
function mapStateToProps(state) {
return {
n: state
}
}
// dispatch 可用于修改状态
function mapDispatchToProps(dispatch) {
return {
add: (number)=> {
// dispatch({type: 'addNum', data: number})
dispatch(createAddAction(number))
},
jian: number => dispatch(createJianAction(number))
}
}
// 使用 connect()()创建并暴露一个容器组件,其中mapStateToProps、mapDispatchToProps用于传给 ui组件,ui组件可以用 props 获取到。
const container = connect(mapStateToProps, mapDispatchToProps)(uiCom)
export default container
UI组件 接收容器组件传递的值:
js
import React, { Component } from 'react'
export default class uiCom extends Component {
addOne = ()=> {
this.props.add(2)
console.log(this.props)
}
render() {
console.log('收到的props', this.props)
return (
<div className="App">
<div>{this.props.n.num}</div>
<button onClick={this.addOne}>+ 1</button>
</div>
);
}
}
props 打印出来的样子
总结
- 创建 reducer 文件,用于放置状态及操作状态
- 使用 legacy_createStore 创建出 store 仓库
- react-redux 让状态传递组件区分 容器组件 和 UI组件,用于简化 redux 操作