redux

132 阅读2分钟

为什么需要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);

项目地址