【react基础】13、redux的简单使用

一、react的状态管理工具简介

redux是一种状态管理工具,它的作用就是能管理状态呗。其实它本质上就是一个全局对象,这个全局对象能被各个组件访问,并且各个组件能操作这个对象(以单向数据流的方式)来读取修改数据等。

  • 其他的还有: flux(这个已经很老了) 、mobx(相对比较新),可以自行了解。

二、redux使用介绍

1、官网介绍:redux官网
2、阮一峰博客文档(推荐):阮一峰redux基本用法介绍 这里面还有一张图,非常好理解,我把它单独拿出来随时观摩观摩。
在这里插入图片描述

注意!!!本文写了不少种方法。

  • 标题三、实际使用基础步骤是最原始的方法。四、简单优化redux使用。是对三、实际使用基础步骤的简单优化。
  • 标题 这个两个版本其实是七(插件版)原理。有些复杂和杂乱,强烈建议跳过,先看。要是还有余力再看。(重要)

三、实际使用基础步骤

本步骤将以todolist为背景:先新建好脚手架,建立components文件夹,再创建todo文件夹(作为todolist模块),创建ToDo.js组件,并在app.js引用组件。

1、安装redux,输入命令npm i redux --save
2、存数据

在components里面新建store文件夹(作为store模块),在store里面新建Store.js 、 Reducer.js 文件。
(1)Reducer.js里面写如下代码:

//  initstate存放最初的数据,根据功能自行定义
var initState  ={
    list:[{id:1,text:'aa'},{id:2,text:'bb'}],
    genId:2
}

//  reducer 有两个参数:
//  state =初始值   state 修改的数据的当前状态 只读,要创建副本   原理:function dou(a=0) {return a*2}
//  action  动作  是一个对象 必须有 type属性  必须返回状态
export const reducer = (state =initState , action) => {
    switch (action.type) {
        case 'ADD':
       	   //  以下代码根据实际需求修改,注意,state是只读属性,必须建立副本来使用
            var newState = {...state};
            newState.genId++;
            newState.list.push({id:newState.genId,text:action.text})  ///这个action.text是修改数据的时候传的值,在后面第 4 步有讲。
            return newState;
        default:
            return state
    }
}

(2)在Store.js里面引入redux和reducer,创建并导出store。

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

var store = createStore(reducer);

export default store;
3、取数据

(1)引入storeimport store from '../store/store';
(2)通过 store.getState().state的变量 取数据。

 constructor() {
        super();
        this.state = {
            list:store.getState().list,  //取数据
             str:''
          }
    }
4、改数据

(1)在你的模块里面(本例是todo模块),新建文件ActionCreator.js,在里面写如下代码:

export default {
	//	 这个名字是随便取的,text这个参数课传可不传
    gipAction(text){
        return {
            type:"ADD",
            text   // es6新写法,等价于text:text
        }
    }
}

(2) 在你的模块里面(本例是todo模块) 引入ActionCreator.jsimport actionCreator from './actionCreator'

(3)抛发动作:store.dispatch(动作)

store.dispatch(actionCreator.gipAction(this.text.value))

注:reducer 将会判断动作类型(type)、创建state的副本、修改、返回新状态

(4)监听数据变化,store.getState().变量 拿到最新状态,然后在组件里设置订阅subscribe。

constructor() {
      super();
      this.getInputValue = this.getInputValue.bind(this);
      this.state = {
          list:store.getState().list,
          str:''
        }
      //监控store里的数据变化
      store.subscribe(this.sub.bind(this))
  }
  sub(){
        this.setState({
            list:store.getState().list
        })
    }

本案例代码:todolist案例

四、简单优化redux使用。

1、分模块使用reducer

(1)把以前写在store里面的reducer放在todolist页面。

var initState  ={
    list:[{id:1,text:'aa'},{id:2,text:'bb'}],
    genId:2
}
export const todoReducer = (state =initState , action) => {
    console.log(action)
    switch (action.type) {
        case 'ADD':
            var newState = {...state};
            newState.genId++;
            newState.list.push({id:newState.genId,text:action.text})
            console.log(newState);
            return newState;
        default:
            return state
    }
}

(2)把store里面新建reducers模块,作用是:总和todolist或其他模块。

import {combineReducers} from 'redux';
import {todoReducer} from '../todolist/reducer'

var reducer = combineReducers({
    todo:todoReducer
})

export default reducer;

(3)把模块里面取数据的加上模块名。

constructor() {
        super();
        this.state = {
            list:store.getState().todo.list  //取数据时加上模块名(store里面导入时的模块名字)
          }
    }
2、把方法名单独列到文件里。

(1)在store文件夹里面,新建actionType.js,写如下内容:

export const ADD= 'ADD';
export const DEC = 'DEC';

(2)改对应的写方法名的地方。createAction、reducer里面。

  • 在文件顶部一引入actionType,import {ADD,DEC} from '../../store/actionType'
  • 把写了"ADD"字符的地方改为ADD变量就行了。

五、终极优化(组件手工拆分版)

要跟store打交道,又要渲染。有点杂乱。所以目标是把组件拆分成两部分,容器组件和ui组件。

六、最终极优化(context版)

每个个文件都会引入store,就很烦。那么我们怎么解决呢?用context(上下文)来传。

  • createContext() 返回值是context,包含两个对象 Provider 、 Consumer
  • yinr

首先要引入和创建context。
生产者和消费者
新建文件MyProvider
在index里面引入,并包裹

七、最最终极版本(插件版react-redux)

用这个react-redux这个插件有什么好处呢?它帮你做完了三个事情:

  • 自动完成subscribe订阅
  • 完成容器组件的功能
  • context传递store帮你做完了。

使用步骤:
1、安装插件:

npm i react-redux --save

2、准备工作:

以下是在store模块里:

(1)建立store文件夹,新建store.js

import {createStore} from 'redux'
import reducers from './reducers'     //总的reducer

var store = createStore(reducer);

export default store;

(2)在store文件夹里新建reducers,并记得引入combineReducers。

import {combineReducers} from 'redux'
import {counterReducer} from '../components/counter/reducer'  // 自己的模块
 var reducer = combineReducers({
     counter:counterReducer    // 自己的模块
 })

 export default reducer;

以下是在counter模块里:

(3)在components建立counter文件夹,新建reducer.js。写初始值和写counterReducer。

import {INC,DEC} from '../../store/actionType'
var initState = {
  one: 1,
  two: 2,
  three: 3
};

export const counterReducer = (state = initState, action) => {
  var newState = { ...state };
  switch (action.type) {
    case INC:
      newState[action.name]++;
      return newState;
    case DEC:
      newState[action.name]--;
      return newState;
    default:
      return state;
  }
};

(4)记得在store里面的reducers里面引入counter模块的reudcer。

import {combineReducers} from 'redux'
import {counterReducer} from '../components/counter/reducer'  // 引入的counter
 var reducer = combineReducers({
     counter:counterReducer    // counter模块
 })

3、引入和使用Provider:
(1)在index.js引入react-redux、store。把App组件用Provider包裹。

import {Provider} from 'react-redux'; // 引入react-redux
import store from './store'  // 引入store
ReactDOM.render(
     <Provider store={store}>  //用Provider把App组件包裹起来,把store传进去。
        <App />
     </Provider>, document.getElementById('root'));

serviceWorker.unregister();

(2)在counter里面写自己的组件,建立Counter组件。就可以把数据渲染出来了。

import React, { Component } from 'react'
import {connect} from 'react-redux'
import actionCreator from './actionCreator';
class Counter extends Component {
  render() {
    let {inc,name,dec} = this.props;
    return (
      <div>
          <button onClick={dec.bind(this,name)}>-1</button>
          {this.props.v}
        <button onClick={inc.bind(this,name)}>+1</button>
      </div>
    )
  }
}

var mapDispatch ={
    inc:actionCreator.incAction,
    dec:actionCreator.decAction    //把actionCreator里的方法进行改名
}
export default connect(null,mapDispatch)(Counter);

(3)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值