为什么需要redux?
react 只是 DOM 的一个抽象层,并不是 Web 应用的完整解决方案。它没有涉及到:
- 代码结构
- 组件之间的通信
redux是一个用来管理数据状态的UI状态的javascript应用工具。随着JavaScript单页应用(SPA)开发日趋复杂,JavaScript需要管理比任何时候都要多的state(状态),Redux就是降低管理难度的。(Redux支持React,Angular、jQuery甚至纯JavaScript)
redux的存在的意义:
- 把UI组件和业务逻辑的拆分,让UI和业务逻辑完全解耦。UI组件是无状态组件
- 数据推动渲染更清晰
redux工作流程
工作流程要点:
- store必须是唯一的,多个store是坚决不允许,只能有一个store空间。只有store能改变自己的内容,reducer不能改变
- reducer是纯函数,负责计算,返回新的state,让store自己去变更。
- action构造函数只负责创建一个对象并返回,通过store.dispatch派发action
三个常用api:store.getState()、store.dispatch()、store.subscribe()
纯函数定义:
如果函数的调用参数相同,则永远返回相同的结果。它不依赖于程序执行期间函数外部任何状态或数据的变化,必须只依赖于其输入参数。
redux中间件
在Dispatch一个Action之后,到达reducer之前,进行一些额外的操作,就需要用到middleware(中间件)。在实际工作中你可以使用中间件来进行日志记录、创建崩溃报告,调用异步接口或者路由。
Action 发出以后,过一段时间再执行 Reducer,这就是异步。怎么才能 Reducer 在异步操作结束后自动执行呢?这就要用到新的工具:中间件(middleware)
配置redux-thunk
import { createStore, applyMiddleware, compose } from 'redux';
import thunk from 'react-thunk';
import reducer from './reducer';
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ?
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}) : compose;
const enhancer = composeEnhancers(applyMiddleware(thunk));
const store = createStore(
reducer,
enhancer
);
export default store;
配置redux-sage
import { createStore, applyMiddleware, compose } from 'redux';
import createSagaMiddleware from 'redux-saga';
import mySagas from './mySagas';
import reducer from './reducer';
const sagaMiddleware = createSagaMiddleware();
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ?
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}) : compose;
const enhancer = composeEnhancers(applyMiddleware(sagaMiddleware));
sagaMiddleware.run(mySagas);
const store = createStore(
reducer,
enhancer
);
export default store;
配置react-redux
react-redux简化Redux流程。主要provider和connect
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import TodoList from './TodoList';
import store from './store';
import 'antd/dist/antd.css';
const App = ()=> {//提供器
return <Provider store={store}>
<TodoList />
</Provider>
}
ReactDOM.render(<App/>, document.getElementById('root'));
import React from 'react';
import { message } from 'antd';
import { connect } from 'react-redux';
import * as action from "./store/actionCreator";
import TodoListUI from './TodoListUI';
class TodoList extends React.PureComponent {
componentDidMount() {
this.props.getTodoList();
}
handleAddItem = () => {
if (!this.props.inputValue) {
message.warn('请填写数据', 2);
return;
}
this.props.onAddItem();
}
render() {
return (
<TodoListUI
inputValue={this.props.inputValue}
list={this.props.list}
onChangeValue={this.props.onChangeValue}
onAddItem={this.handleAddItem}
onRemoveItem={this.props.onRemoveItem}
/>
);
}
}
const mapStateToProps = (state, ownProps) => { //将state映射到 UI 组件的参数(props)
return {
inputValue: state.inputValue,
list: state.list
}
}
const mapDispatchToProps = (dispatch) => { //将用户对 UI 组件的操作映射成 Action
return {
getTodoList(){
dispatch(action.getTodoList());
},
onChangeValue(e){
const value = e.target.value;
dispatch(action.changeInputAction(value))
},
onAddItem(){
dispatch(action.addItemAction());
},
onRemoveItem(index){
dispatch(action.removeItemAction(index));
}
}
}
export default connect(mapStateToProps, mapDispatchToProps)(TodoList);