学习笔记——react中实现仓库redux


在react可以使用redux包来创建一个数据仓库。

1.下载redux包:

在项目的根目录下,打开命令窗口,输入以下命令: 

yarn add redux

 2.创建仓库:

在src目录下,创建一个store文件夹,在其文件夹内创建一个index.js。 

import { createStore, combineReducers, applyMiddleware } from "redux";
import categoryReducer, { CategoryActions } from './category.js';
import productReducer, { ProductActions } from './product.js';
import cartReducer, { CartActions } from './cart.js';
// 先想好仓库结构,每个子仓库的结构。
// 总reducer
const reducer = combineReducers({
        category: categoryReducer,
        product: productReducer,
        cart: cartReducer
});

const store = createStore(reducer);
export default store;

// 统一导入各自仓库中的ActionsCreate再统一导出。
export {
        CategoryActions,
        ProductActions,
        CartActions
};

其子仓库代码为:

import http from '../utils/http';
// 子reducer
const initState = { listMain: [], listSub: [] };

const ACTIONS = {
        MAIN: Symbol(),
        SUB: Symbol()
};

//  action creator作用是:让组件和仓库通信更优雅
export const CategoryActions = {
        assignListMain: () => async ({ dispatch, getState }) => {
                // getState调用可以拿到当前仓库的state
                let result = await http('/category/list/0');
                dispatch({ type: ACTIONS.MAIN, payload: result });
        },
        assignListSub: fid => async ({ dispatch, getState }) => {
                let result = await http('/category/list/' + fid);
                dispatch({ type: ACTIONS.MAIN, payload: result });
        }
};


const reducer = function(state = initState, action) {
        const { type, payload } = action;
        switch(type) {
                case ACTIONS.MAIN:
                        return Object.assign({}, state, { listMain: [] });
                case ACTIONS.SUB:
                        return Object.assign({}, state, { listSub: [] });
                default:
                        return state;
        }
};

export default reducer;

reducer函数的特点:

1.上一次return的结果,将会作为下一个reducer函数调用的第一个参数。

2.创建一个reducer仓库对象,reducer函数第一次调用时,可以设置一个默认值,表示state的初始状态。不过第一次调用时,第二个参数是没有的,后续的reducer函数调用时,会将第二个参数传过来,reducer函数会根据内部action,返回一个新的state,相当于仓库更新了。

3.action对象:如果一个对象有一个type属性值是字符串。redux认为它是action对象。

3.下载redux-thunk包:

 为了使仓库的dispatch方法能够接受函数作为参数。将异步耗时的ajax代码放到dispatch的参数函数中。需要下载redux-thunk包。

yarn add redux-thunk

4.redux-thunk包使用:

dispatch函数默认只能接收actions对象,不能接收函数作为对象,所以我们要用第三方包redux-thunk来增强仓库的dispatch方法,让其能接收函数。给dispatch一个函数,dispatch会立即执行,且会强制它state和dispatch函数自身作为这个立即执行函数的参数!(这个立即执行函数中可以包含异步耗时的代码,相当于仓库发了ajax) 

使用后,可以在仓库中发送ajax。

// index.js文件需要改变的内容
import { createStore, combineReducers, applyMiddleware } from "redux";
import thunk from 'redux-thunk';

const store = createStore(reducer, applyMiddleware(thunk));
// 子仓库发送ajax的代码
export const CategoryActions = {
    assignListMain: () => async ({ dispatch, getState}) => {
        // getState调用可以拿到当前仓库的state
        let result = await http('/category/list/0');
        dispatch({ type: ACTIONS.MAIN, payload: result });
    }
}

5.下载react-redux包:

为了在根实例index.js中导入该包,就能将redux仓库和项目联系起来。

yarn add react-redux

 需要从react-redux中先解构除Provider,再用Provider包裹主根组件,并在标签中导入仓库store。

// 根实例index.js
// 在使用jsx对象时,必须引入react
// 根实例,将根组件App渲染到挂载点
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.jsx';
import { HashRouter } from 'react-router-dom';
import store from './store';
import { Provider } from 'react-redux';

ReactDOM.render(
        <Provider store={ store }>
                <HashRouter>
                        <App />
                </HashRouter>
        </Provider>,
        document.getElementById('root')
);

6.组件中使用仓库:

在随便一个页面级组件中,拿出仓库中的数据,并且通知仓库修改数据。

import  React, { Component } from 'react';
import { MiNav } from '../../components';
import { connect } from 'react-redux';
import { TestActions } from '../../store';

class Home extends Component {
    render() {
        return (
            <div>这是主页{ this.props.a }
                <MiNav />
                <button onClick={() => this.props.change(123123)}>
                    test中的a值123123
                </button>
            </div>
                        
        );
   }
}

const mapStateToProps = (state, props) => ({
        a: state.test.a
});

const mapDispatchToProps = (dispatch, props) => ({
        change: value => dispatch(TestActions.changeA(value))
});

export default connect(mapStateToProps, mapDispatchToProps)(Home);

方法用react-redux包中的connect方法产生一个高阶组件,让该组件称为一个连接仓库和Home组件的中间组件。

connect中需要两个函数作为参数,两个函数的返回值将会assign合并到服务(包裹)组件的props中。

第一个参数:mapStateToProps(state,props)。主要作用是将要服务的组件中从仓库state中映射数据。该函数中有两个参数:

state为redux仓库中当前的state,props为父组件向本组件传递的值。

第二个参数:mapDispatchToProps(dispatch,props)。主要作用就是将仓库中的dispatch方法封装成函数,映射到包裹组件的props中以供使用,让包裹组件可以修改redux中的数据。

dispatch是redux中的dispatch函数。


以上就是react中实现仓库的方法。需要下载的包比较多。使用仓库时,需要预先想好仓库的结构,希望存放和修改的数据以及如何对数据进行修改。

猜你喜欢

转载自blog.csdn.net/qq_41339126/article/details/109583877