zoukankan      html  css  js  c++  java
  • redux、react-redux、redux-thunk、redux-saga使用及dva对比

    一、redux使用

      Redux的核心概念其实很简单:将需要修改的state都存入到store里,发起一个action用来描述发生了什么,用reducers描述action如何改变state tree 。创建store的时候需要传入reducer,真正能改变store中数据的是store.dispatch API。

    1、src下新建store文件夹,新建index.js作为store的输出文件

    2、store文件夹下新建index.js文件

    3、新建reducer.js ,actionTypes.js文件

    4、组件引入store

    import React, { Component } from 'react';
    import { Input ,Button,List } from 'antd';
    import store from './store';
    import {CHANGE_INPUT_VALUE,ADD_TODO_ITEM,DELETE_TODO_ITEM} from  './store/actionTypes'
    
    class TodoList extends Component {
        constructor(props) {
            super(props);
            this.state = store.getState();
            this.handleStoreChange = this.handleStoreChange.bind(this);
            this.handleBtnClick = this.handleBtnClick.bind(this);
            this.handleInputChange = this.handleInputChange.bind(this);
            store.subscribe(this.handleStoreChange)
        }
        
        handleInputChange(e) {
            const action = {
                type: CHANGE_INPUT_VALUE,
                value: e.target.value
            }
            store.dispatch(action)
        }
    
        handleBtnClick() {
            const action = {
                type: ADD_TODO_ITEM
            }
            store.dispatch(action)
        }
        
        render() {
            return (
                <div style={{marginTop:'20px',marginLeft:'15px'}}>
                    <div>
                        <Input 
                            value={this.state.inputValue} 
                            placeholder="input" 
                            style={{'300px'}}
                            onChange={this.handleInputChange}
                        />
                        <Button onClick={this.handleBtnClick} type="primary">Primary</Button>
                    </div>
                    <List
                        style={{marginTop:'15px','300px'}}
                        bordered
                        dataSource={this.state.list}
                        renderItem={(item,index) => <List.Item onClick={this.handleItemDelete.bind(this,index)}>{item}</List.Item>}
                        />
                </div>
            )
        }
    
        handleStoreChange() {
            this.setState(store.getState())
        }
        handleItemDelete(index) {
            const action = {
                type: DELETE_TODO_ITEM,
                index
            }
            store.dispatch(action)
        }
    }
    
    export default TodoList;

    5、使用redux-devtool

    import { createStore } from 'redux';
    import reducer from './reducer'
    
    
    const store = createStore(
        reducer,
        window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
    );
    
    export default store;

     6、actionTypes.js代码如下

    export const  CHANGE_INPUT_VALUE = 'change_input_value';
    export const  ADD_TODO_ITEM = 'add_todo_item';
    export const  DELETE_TODO_ITEM = 'delete_todo_item';

    7、reducer.js代码如下

    import {CHANGE_INPUT_VALUE,ADD_TODO_ITEM,DELETE_TODO_ITEM} from  './actionTypes'
    const defaultState = {
        inputValue:'aaa',
        list:['1','2']
    }
    
    export default (state = defaultState,action) => {
        if(action.type === CHANGE_INPUT_VALUE) {
            const newState = JSON.parse(JSON.stringify(state));
            newState.inputValue = action.value;
            return newState;
        }
        if(action.type === ADD_TODO_ITEM) {
            const newState = JSON.parse(JSON.stringify(state));
            newState.list.push(newState.inputValue);
            newState.inputValue = '';
            return newState;
        }
        if(action.type === DELETE_TODO_ITEM) {
            const newState = JSON.parse(JSON.stringify(state));
            newState.list.splice(action.index,1);
            return newState;
        }
        return state;
    }

    8、优化:使用actionCreactor.js来统一管理action

    二、引入react-redux

    1.在index.js里引入react-redux及store

    import React from 'react';
    import ReactDOM from 'react-dom';
    import 'antd/dist/antd.css';
    import './index.css';
    import App from './TodoList';
    import * as serviceWorker from './serviceWorker';
    import store from './store'
    import { Provider } from 'react-redux';
    
    const ProviderApp = (
        <Provider store={store}>
            <App></App>
        </Provider>
    )
    
    ReactDOM.render(ProviderApp, document.getElementById('root'));
    serviceWorker.unregister();

    2.在组件里做connect

    import React, { Component } from 'react';
    import { Input ,Button,List } from 'antd';
    import {CHANGE_INPUT_VALUE,ADD_TODO_ITEM} from  './store/actionTypes'
    import {connect} from 'react-redux';
    
    
    class TodoList extends Component {
        render() {
            const {handleInputChange,handleBtnClick} = this.props
            return (
                <div style={{marginTop:'20px',marginLeft:'15px'}}>
                    <div>
                        <Input 
                            value={this.props.inputValue} 
                            placeholder="input" 
                            style={{'300px'}}
                            onChange={handleInputChange}
                        />
                        <Button onClick={handleBtnClick} type="primary">Primary</Button>
                    </div>
                    <List
                        style={{marginTop:'15px','300px'}}
                        bordered
                        dataSource={this.props.list}
                        renderItem={(item,index) => <List.Item>{item}</List.Item>}
                        />
                </div>
            )
        }
        
    }
    const mapStateToProps = (state) => {
        return {
            inputValue: state.inputValue,
            list : state.list
        }    
    }
    
    const mapDispatchToProps = (dispatch) => {
        return {
            handleInputChange(e) {
                const action = {
                    type: CHANGE_INPUT_VALUE,
                    value: e.target.value
                }
                dispatch(action)
            },
            handleBtnClick() {
                const action = {
                    type: ADD_TODO_ITEM
                }
                dispatch(action)
            },
    
        }
    }
    
    export default connect(mapStateToProps,mapDispatchToProps)(TodoList);

    三、redux-thunk使用

    1.中间件的概念

      dispatch一个action之后,到达reducer之前,进行一些额外的操作,就需要用到middleware。你可以利用 Redux middleware 来进行日志记录、创建崩溃报告、调用异步接口或者路由等等。
      换言之,中间件都是对store.dispatch()的增强。redux-thunk就是用来异步操作,比如接口请求等。

    2.引入redux-thunk

    import { applyMiddleware, createStore } from 'redux';
    import thunk from 'redux-thunk';
     const store = createStore(
      reducers, 
      applyMiddleware(thunk)
    );
    

    3.这样就可以再actionCreactor中创建一个带异步函数的方法了

    export const getTodoList = () => {
        return () => {
            axios.get('./list').then((res)=>{
                const data = res.data;
                const action  = initListAction(data);
                StorageEvent.dispatch(action);
            })
        }
    }

    四、redux-saga使用

      redux-saga是一个用于管理redux应用异步操作的中间件,redux-saga通过创建sagas将所有异步操作逻辑收集在一个地方集中处理,可以用来代替redux-thunk中间件。

    1.在store.js里引入redux-saga

    import { createStore, applyMiddleware } from 'redux'
    import createSagaMiddleware from 'redux-saga'
    
    import reducer from './reducers'
    import mySaga from './sagas'
    
    // create the saga middleware
    const sagaMiddleware = createSagaMiddleware()
    // mount it on the Store
    const store = createStore(
      reducer,
      applyMiddleware(sagaMiddleware)
    )
    
    // then run the saga
    sagaMiddleware.run(mySaga);
    export default store;

    2.新建 saga.js

    import { call, put, takeEvery, takeLatest } from 'redux-saga/effects'
    import Api from '...'
    
    // worker Saga: will be fired on USER_FETCH_REQUESTED actions
    function* fetchUser(action) {
       try {
          const user = yield call(Api.fetchUser, action.payload.userId);
          yield put({type: "USER_FETCH_SUCCEEDED", user: user});
       } catch (e) {
          yield put({type: "USER_FETCH_FAILED", message: e.message});
       }
    }
    function* mySaga() {
      yield takeEvery("USER_FETCH_REQUESTED", fetchUser);
    }
    
    export default mySaga;

     五、dva对比

    dva使用可以参考这个博客:https://www.cnblogs.com/superSmile/p/9972344.html

  • 相关阅读:
    游标cursor
    SQL: EXISTS
    LeetCode Reverse Integer
    LeetCode Same Tree
    LeetCode Maximum Depth of Binary Tree
    LeetCode 3Sum Closest
    LeetCode Linked List Cycle
    LeetCode Best Time to Buy and Sell Stock II
    LeetCode Balanced Binary Tree
    LeetCode Validate Binary Search Tree
  • 原文地址:https://www.cnblogs.com/superSmile/p/11209703.html
Copyright © 2011-2022 走看看