redux、react-redux、redux-thunk、redux-saga使用及dva對比

1、redux使用

  Redux的核心概念其實很簡單:將須要修改的state都存入到store裏,發起一個action用來描述發生了什麼,用reducers描述action如何改變state tree 。建立store的時候須要傳入reducer,真正能改變store中數據的是store.dispatch API。

一、src下新建store文件夾,新建index.js做爲store的輸出文件javascript

二、store文件夾下新建index.js文件css

三、新建reducer.js ,actionTypes.js文件html

四、組件引入storejava

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={{width:'300px'}}
                        onChange={this.handleInputChange}
                    />
                    <Button onClick={this.handleBtnClick} type="primary">Primary</Button>
                </div>
                <List
                    style={{marginTop:'15px',width:'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;

五、使用redux-devtoolreact

import { createStore } from 'redux';
import reducer from './reducer'


const store = createStore(
    reducer,
    window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
);

export default store;

 六、actionTypes.js代碼以下ios

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

七、reducer.js代碼以下redux

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;
}

八、優化:使用actionCreactor.js來統一管理actionaxios

2、引入react-redux

1.在index.js裏引入react-redux及storeantd

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.在組件裏作connectapp

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={{width:'300px'}}
                        onChange={handleInputChange}
                    />
                    <Button onClick={handleBtnClick} type="primary">Primary</Button>
                </div>
                <List
                    style={{marginTop:'15px',width:'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);

3、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);
        })
    }
}

 

4、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;

 5、dva對比

dva使用能夠參考這個博客:http://www.javashuo.com/article/p-hfndcfzq-hn.html

相關文章
相關標籤/搜索