Redux
专注于状态管理的库
- Redux专注于状态管理和react解耦
- 单一状态,单向数据流
- 核心概念:store,state,action,reducer
使用
- 安装
npm install redux --save
- 基础使用
import {createStore} from 'redux';
//新建store
//通过reducer建立
//根据老的state和action 生成新的state
function counter(state = 0, action) {
switch (action.type) {
case '赚了1块钱':
return state + 1;
case '花了1块钱':
return state - 1;
default:
//初始状态
return 10;
}
}
const store = createStore(counter);
console.log("开始手里有" + store.getState() + "块钱");
function listenner() {
const current = store.getState();
console.log(`现在手里有${current}块钱`);
}
//订阅,每次状态更换都会触发linstenner函数
store.subscribe(listenner);
//派发事件 传递action
store.dispatch({
type: '赚了1块钱'
});
store.dispatch({
type: '赚了1块钱'
});
store.dispatch({
type: '赚了1块钱'
});
Redux 和 React 一起使用
- 把store.dispatch方法传递给组件,内部可以调用修改状态。
- Subscribe订阅render函数,每次修改都重新渲染。
- Redux相关内容,移到单独的文件index.redux.js单独管理。
index.js
import React from 'react';
import ReactDom from 'react-dom';
import {createStore} from 'redux';
import {counter} from './index.redux';
import App from './App';
//创建store
const store = createStore(counter);
function render() {
ReactDom.render(
<App store = {store} />,
document.getElementById('root')
);
}
render();
//重新渲染render
store.subscribe(render);
index.redux.js
const makeMoney = "赚了1块钱";
const spendMoney = "花了1块钱";
//状态管理
export function counter(state = 0, action) {
switch (action.type) {
case makeMoney:
return state + 1;
case spendMoney:
return state - 1;
default:
//初始状态
return 10;
}
}
//action creator 创建action
export function MakeMoney() {
return {type:makeMoney}
}
export function SpendMoney() {
return {type:spendMoney}
}
App.js
import React, {Component} from 'react';
import {
Button
} from 'antd-mobile';
export default class App extends Component {
// constructor(props){
// super(props);
// }
render() {
//属性获取可以直接用
const store = this.props.store;
//获取当前状态
const money = store.getState();
//获取方法
const MakeMoney = this.props.MakeMoney;
const SpendMoney = this.props.SpendMoney;
return (
<div>
<h1 align='center'>现在手里有{money}块钱</h1>
<Button type='primary' onClick={() => store.dispatch(MakeMoney())}>赚钱</Button>
<br/>
<Button type='primary' onClick={() => store.dispatch(SpendMoney())}>花钱</Button>
</div>
)
}
}
处理异步、调试工具、更优雅的和react结合
处理异步
- redux-thunk插件
npm install redux-thunk --save
- index.js添加和修改代码
//增加applyMiddleware模块
import {createStore,applyMiddleware} from 'redux';
//引入thunk
import thunk from 'redux-thunk';
- index.redux.js添加函数
export function MakeMoneyAsync() {
return dispatch=>{
setTimeout(()=>{
dispatch(MakeMoney());
},2000);
};
}
2.使用applyMiddleware开启thunk中间件
- Action可以返回函数,使用dispatch提交action
调试工具
- 在chrome安装Redux调试工具
Redux DevTools
- 使用
- 新建store的时候判断window.devToolsExtension
- 使用compose结合thunk和window.devToolsExtension
- 开发者工具中的Redux选项卡下可以看到实时state - 代码修改index.js文件
import React from 'react';
import ReactDom from 'react-dom';
//增加applyMiddleware模块
import {createStore,applyMiddleware,compose} from 'redux';
//引入thunk
import thunk from 'redux-thunk';
import {counter,MakeMoney,SpendMoney,MakeMoneyAsync} from './index.redux';
import App from './App';
//修改代码判断系统是否存在函数,若没有则返回空
const ReduxDevTools = window.devToolsExtension?window.devToolsExtension():f=>f;
//创建store
const store = createStore(counter,compose(
applyMiddleware(thunk),
ReduxDevTools
));
function render() {
ReactDom.render(
<App store = {store} MakeMoney={MakeMoney} SpendMoney={SpendMoney} MakeMoneyAsync={MakeMoneyAsync}/>,
document.getElementById('root')
);
}
render();
//订阅render函数,状态变化重新渲染
store.subscribe(render);
-
运行结果
使用react-redux优雅的链接react和redux
- 安装
npm install react-rudex --save
- 具体使用
- Provide组件在应用最外层,传入store即可,只用一次
- Connect负责从外部获取组件需要的参数
- Connect可以用装饰器的方式来写
- 修改后的代码
//index.js
import React from 'react';
import ReactDom from 'react-dom';
//增加applyMiddleware模块
import {createStore, applyMiddleware, compose} from 'redux';
//引入thunk
import thunk from 'redux-thunk';
//引入Provider组件
import {Provider} from 'react-redux';
import {counter} from './index.redux';
import App from './App';
//创建store
const store = createStore(counter, compose(
applyMiddleware(thunk),//创建异步Redux
//引入Chrome中的Redux开发者工具
//修改代码判断系统是否存在函数,若没有则返回空
window.devToolsExtension ? window.devToolsExtension() : f => f
));
//最外层使用Provide组件,属性只传store,内部App组件内不需要任何属性
ReactDom.render(
(<Provider store={store}>
<App/>
</Provider>),
document.getElementById('root')
);
//App.js
import React, {Component} from 'react';
import {
Button
} from 'antd-mobile';
//引入connect专门用来连接
import { connect } from 'react-redux';
//引入动作
import {
MakeMoneyAsync,
MakeMoney,
SpendMoney
} from './index.redux';
class App extends Component {
render() {
return (
<div>
<h1 align='center'>现在手里有{this.props.money}块钱</h1>
<Button type='primary' onClick={this.props.MakeMoney}>赚钱</Button>
<br/>
<Button type='primary' onClick={this.props.SpendMoney}>花钱</Button>
<br/>
<Button type='primary' onClick={this.props.MakeMoneyAsync}>过了2秒又赚钱</Button>
</div>
)
}
}
//使用connect装饰器
const mapStatetoProps = (state) => {
return {money: state};
};
const actionCreators = {
MakeMoneyAsync,
MakeMoney,
SpendMoney
};
//传递属性和方法
App = connect(mapStatetoProps,actionCreators)(App);
export default App;
使用装饰器优化connect
- 弹出配置文件
npm run eject
- 使用插件
npm install babel-plugin-transform-decorators-legacy --save-dev
- 在package.json中加上plugins配置
在babel下的plugins内添加
[
"transform-decorators-legacy"
]
- 代码修改 App.js
//使用connect装饰器
// const mapStatetoProps = (state) => {
// return {money: state};
// };
// const actionCreators = {
// MakeMoneyAsync,
// MakeMoney,
// SpendMoney
// };
//传递属性和方法
//App = connect(mapStatetoProps,actionCreators)(App);
//删除上面代码并改为如下
//将@connect挪到class上面
@connect(
//需要的属性
state=>({money:state}),
//需要的方法,自动dispatch
{ MakeMoneyAsync, MakeMoney, SpendMoney}
)
export default class App extends Component {
...
}