- 安装Redux
npm install --save redux
- 在 src 目录下新建 store 文件夹,在store中新建 index.js 和 reducer.js 文件。
- 在 index.js 中通过 createStore 方法创建 store,将 reducer 作为参数传给 createStore 方法 (省了一点懒,reducer内容在后面)
// index.js
import { createStore } from "redux";
import reducer from './reducer';
const store = createStore(
reducer,
// 运行 已安装的redux调试工具,可以在Chrome应用商店里面找到(只有科学上网才能找到的哈)
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
)
export default store;
// reducer.js 声明各组件需要的state变量
// state是只读的,能改变state的唯一方式是通过触发action来修改 !!!
const defaultState = {
inputValue: 'write something',
list: ['a', 'b', 'c']
}
export default (state = defaultState, action) => {
// 根据组件中传递过来的action.type决定要修改的值
if (action.type === 'changInput') {
// 深拷贝,reducer只接收,不能直接修改state
let newState = JSON.parse(JSON.stringify(state))
newState.inputValue = action.value
return newState
}
if (action.type === 'addItem') {
let newState = JSON.parse(JSON.stringify(state))
newState.list.push(newState.inputValue)
newState.inputValue = ''
return newState
}
return state
}
- 在组件中引入store,并与state绑定
import React, {Component} from 'react';
import { Input, Button, List } from 'antd';
import store from '../../store';
class TodoList extends Component {
constructor(props) {
super(props)
this.state = store.getState() // 返回当前store中的state的数据
// 绑定this
this.storeChange = this.storeChange.bind(this)
this.changeInputValue = this.changeInputValue.bind(this)
this.clickBtn = this.clickBtn.bind(this)
// 注册监听store,store变化后调用组件的storeChange方法更新组件的state
store.subscribe(this.storeChange)
}
// store 变化后,更新组件的 state
storeChange () {
this.setState(store.getState())
}
// 方法中声明 action 传递给 store,让 store 去根据 action.type 在 reducer 中做判断,
// 决定将 reducer 中哪个值改为 action.value,并返回一个新 state 让 store 通知组件去更新
changeInputValue (e) {
const action = {
type: 'changInput',
value: e.target.value
}
store.dispatch(action)
}
clickBtn () {
const action = { type: 'addItem'}
store.dispatch(action)
}
render() {
return (
<div>
<div>
<Input placeholder={this.state.inputValue} onChange={this.changeInputValue} />
<Button type='primary' onClick={this.clickBtn}>增加</Button>
</div>
<div>
<List bordered
dataSource={this.state.list}
renderItem={item=>(<List.Item }>{item}</List.Item>)}
/>
</div>
</div>
);
}
}
export default TodoList;
如果你有耐心一直看到这里,那么就会发现,在组件里面派发了很多action,也有很多的type,当文件多了之后要查找action.type就会变得非常麻烦。
解决方法就是将action以及actionType统一管理:
在store文件夹中新建actionType.js文件,统一管理type
export const CHANGE_INPUT = 'changeInput'
export const ADD_ITEM = 'addItem'
。。。。。
在store文件夹中新建actionCreators.js文件,管理派发的action
// actionCreators.js
import { CHANGE_INPUT, ADD_ITEM} from './actionTypes'; // 导入type
export const changeInputAction = (value) => ({
type: CHANGE_INPUT,
value
})
export const addItemAction = () => ({
type: ADD_ITEM
})
.......
1、在组件里面引入actionCreators.js,还是用上面的代码吼
import React, {Component} from 'react';
import { Input, Button, List } from 'antd';
import store from '../../store';
import { changeInputAction, addItemAction } from '../../store/actionCreators';
class TodoList extends Component {
constructor(props) {
super(props)
this.state = store.getState() // 返回当前store中的state的数据
// 绑定this
this.storeChange = this.storeChange.bind(this)
this.changeInputValue = this.changeInputValue.bind(this)
this.clickBtn = this.clickBtn.bind(this)
// 注册监听store,store变化后调用组件的storeChange方法更新组件的state
store.subscribe(this.storeChange)
}
// store 变化后,更新组件的 state
storeChange () {
this.setState(store.getState())
}
// 方法中声明 action 传递给 store,让 store 去根据 action.type 在 reducer 中做判断,
// 决定将 reducer 中哪个值改为 action.value,并返回一个新 state 让 store 通知组件去更新
changeInputValue (e) {
const action = changeInputAction(e.target.value)
store.dispatch(action)
}
clickBtn () {
const action = addItemAction()
store.dispatch(action)
}
render() {
return (
.......
);
}
}
export default TodoList;
2、在store => reducer.js里面引入actionType.js
import { CHANGE_INPUT, ADD_ITEM } from './actionType'
const defaultState = {
inputValue: 'write something',
list: ['a', 'b', 'c']
}
export default (state = defaultState, action) => {
// 根据组件中传递过来的action.type决定要修改的值
if (action.type === CHANGE_INPUT) {
// 深拷贝,reducer只接收,不能直接修改state
let newState = JSON.parse(JSON.stringify(state))
newState.inputValue = action.value
return newState
}
if (action.type === ADD_ITEM) {
let newState = JSON.parse(JSON.stringify(state))
newState.list.push(newState.inputValue)
newState.inputValue = ''
return newState
}
return state
}
-
Redux 特点
- 统一的状态管理,一个应用中只能有一个store
- 仓库中管理了一个状态树(stateTree)
- store不能直接修改,只能通过派发器(dispatch)派发一个动作(action)
- 更新state的逻辑封装在reducer中,reducer只接受state,不能改变state
- reducer必须是一个纯函数,最好不在其中调用后端接口
-
什么时候使用Redux?
如果UI层非常简单,没有很多互动,Redux就是不必要的,用了反而增加复杂性。
- 用户使用方式非常简单
- 用户之间没有协作
- 不需要与服务器大量交互,也没有使用Webscoket
- 视图层(view)只从单一来源获取数据
Redux 的适用场景:多交互、多数据源。
- 用户的使用方式复杂
- 不同身份的用户有不同的使用方式(比如普通用户和管理员)
- 多个用户之间可以协作
- 与服务器大量交互,或者使用webscoket
- view要从多个来源获取数据
从组件角度看,如果你的应用有以下场景,可以考虑使用 Redux。
- 某个组件的状态需要共享
- 某个状态需要在任何地方都可以拿到
- 一个组件需要改变全局状态
- 一个组件需要改变另一个组件的状态
参考:https://www.cnblogs.com/yuanjili666/p/11578519.html