其實你會發現redux並沒那麼難!

Redux特色

  • 統一的狀態管理,一個應用中只有一個倉庫(store)
  • 倉庫中管理了一個狀態樹(statetree)
  • 倉庫不能直接修改,修改只能經過派發器(dispatch)派發一個動做(action)
  • 更新state的邏輯封裝到reducer中,reducer是純函數

Redux流程圖

Rdeux中重要對象說明

store

是一個數據倉庫,一個應用中store是惟一的,它裏面封裝了state狀態,當用戶想訪問state的時候,只能經過store.getState來取得state對象。css

action

action描述了一個更新state的動做,它是一個對象,其中type屬性是必須有的,reducer會根據type來指定某動做和要修改的值。react

{
    type: FETCH_POSTS,
    payload: posts  // 數據源
}
複製代碼

dispatch

dispatch是一個方法,它用於派發一個action,這是惟一的可以修改state的方法。git

fetch("https://jsonplaceholder.typicode.com/posts")
    .then(
        posts => dispatch({
            type: FETCH_POSTS,
            payload: posts
        })   
    )
複製代碼

reducer

reducer是更新state的核心,它裏面已經封裝好了更新state的邏輯,接受兩個參數,state和action,將新值更新到舊的state對象上返回。github

// 根據action的type,返回不一樣數據

switch (action.type) {
    case FETCH_POSTS:
        return {
            ...state,
            items: action.payload
        };
    default:
        return state;
}
複製代碼

React中使用Redux

項目目錄結構

屏幕快照 2019-09-02 下午2.54.02.pngjson

入口文件index.js

import { Provider } from 'react-redux';
import { store } from './redux/store';

// Provider包裹以後,全部的組件均可以拿到store庫中數據
<Provider store={store}>
    // 項目中經常使用Provider包裹最底層父組件,以保證全部組件都能共享數據
    <Index />
</Provider>
複製代碼

數據倉庫store.js

  1. 引入所需文件和插件
import {applyMiddleware, createStore} from "redux";
import rootReducer from './reducers/index.js';
import thunk from 'redux-thunk'; // thunk做用是異步的分發action

const middleware = [thunk]; // 中間件
const initialState = {};
複製代碼
  1. 經過createStore方法建立庫,接受三個參數(reducer,state,中間件)
// applyMiddleware將全部中間件組成一個數組並依次執行
export const store = createStore(
    rootReducer,
    initialState,
    applyMiddleware(...middleware),
);
複製代碼

actions/postAction.js

// 分發操做
export const fetchPosts = () => dispatch => {
    fetch("https://jsonplaceholder.typicode.com/posts")
        .then(res => res.json())
        .then(posts => dispatch({
            type: 'FETCH_POSTS', // type是必需要有的
            payload: posts // 有效數據
        }));
};
複製代碼

reducers/postReducer.js

const initialState = {
    items: [],
    item: {}
};

// reducer接受兩個參數,第一個是state,第二個是action
export default function (state = initialState, action) {
    switch (action.type) {
        case FETCH_POSTS:
            return {
                ...state,
                items: action.payload
            };
        default:
            return state;
    }
}
複製代碼

組件觸發action

  1. 以components中的Posts組件來講明,引入所需數據和方法
import {connect} from 'react-redux';
import {fetchPosts} from "../redux/actions/postActions";

@connect(state => {
    let {items, item} = state.posts;
    return {
        items,
        item
    }
},{fetchPosts})
複製代碼
  1. 經過this.props引入
componentDidMount () {
    this.props.fetchPosts();
}

componentWillReceiveProps (nextProps) {
    if(nextProps.item){
        this.props.items.unshift(nextProps.item);
    }
}
複製代碼

項目完整代碼

github.com/GaoHeming11…redux

補充

引入第三方庫antd時按需加載

yarn add babel-plugin-import --save

// 在package.json中添加
"babel": {
    "presets": [
      "react-app"
    ],
    "plugins": [
      [
        "import",
        {
          "libraryName": "antd",
          "style": "css"
        }
      ]
    ]
}
複製代碼

connect裝飾器寫法

  1. 未用裝飾器寫法
// 將最新的state映射到當前組件,經過mapStateToProps訂閱store
const mapStateToProps = state => ({
    posts: state.posts.items,
});

// 將當前組件Posts和action進行連接
// connect接受兩個參數,第二個參數裏面能夠包含多個方法
export default connect(mapStateToProps,{fetchPosts})(Posts)
複製代碼
  1. 使用裝飾器寫法
yarn add babel-plugin-transform-decorators-legacy

// 可省略如上步驟,在頭部引入所需state和action,而後直接導出組件
@connect(state => {
    let {
        items,
        item
    } = state.posts;
    return {
        items,
        item
    }
},{fetchPosts}),

export default Posts;
複製代碼

剛剛加入掘金社區,歡迎提出寶貴的意見,一塊兒進步學習。數組

相關文章
相關標籤/搜索