Redux(状态管理JS库)的使用

Posted 空谷丶幽兰

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Redux(状态管理JS库)的使用相关的知识,希望对你有一定的参考价值。

1.redux是什么 ☀️

🌸 redux是一个专门用于状态管理的JS库

1.作用范围:它可以用在react,angular,Vue等项目中,但基本与react配合使用,(Vue一般使用Vuex)
2.作用:集中式管理react应用中多个组件的共享状态

2.什么时候用redux 🌀

1.某个组件的状态,需要让其他组件可以随时拿到(共享)
2.一个组件需要改变另一个组件的状态 (通信)
3.总体原则:能不用就不用,如果不用比较吃力才考虑使用
4.一般使用消息订阅与发布机制

3.redux的基本原则 ❄️

🌼 唯一数据源
🌼 保持状态只读
🌼 数据改变只能通过纯函数完成

1.唯一数据源指的是应用的状态数据,应该只存储在唯一的一个store上
2.保持状态只读,就是说不能去直接修改状态,要修改store的状态,必须要通过派发一个action对象完成。
(驱动用户界面渲染,就要改变应用的状态,但是改变状态的方法不是去修改状态上的值,而是创建一个新的状态对象返回给Redux,由Redux完成新的状态组装)
3.这里说的纯函数就是Reducer

在Redux中,reducer的函数签名:
🌐 reducer(state,action)

	第一个参数state是当前的状态
	第二个参数action是接受到的action对象,
	而reducer函数要做的就是根据state和action的值产生一个新对象返回
	注意reducer必须是一个纯函数,也就是说函数的返回结果必须完全由参数state和action决定,同时也不能修改参数state和action对象

4.redux的三个核心概念 ⚠️

🌌 action

	1.动作的对象
	2.包含2个属性
		type:标识属性,值为字符串,唯一,必要属性
		data:数据属性,值类型任意,可选属性
	3.例如:  {type:"increment",data:10}

🌌 reducer

	1.用于初始化状态,加工状态
	2.加工时,根据旧的state和action,产生新的state的纯函数

🌌 store

	1.将state,action,redux联系在一起
	2.如何得到此对象?
	   ①import  {createStore} from 'redux'
	   ②import reducer from './reducer'
	   ③const store = createStore(reducer)
	3.此对象的功能?
	  ①getState():得到state
	  ②dispatch(action):分发action,触发render调用,产生新的state
	  ③subscribe(listener):注册监听,当产生了新的state时,自动调用

5.redux的核心API 🎯

🎬 createStore()

	1.作用:创建包含指定reducer的store对象

🎬 store对象

	1.作用:redux库最核心的管理对象
	2.内部维护着:
				state
				reducer
	3.核心方法:
				①getState()
				②dispatch(action)
				③store.subscribe(listener)
	4.具体实现
				store.getState()
				store.dispatch({type:'increment',data:100})
				store.subscibe(render)

🎬 action

	1.action有两种值:
				 object类型的action     -----被称为同步类型的action
				 function类型的action   -----被称为异步类型的action
	2.异步action:延迟的动作不想交给组件自身,想交给action,想要对状态进行操作,但是具体的数据靠异步返回
	3.怎样使用:yarn add  redux-thunk ,并配置在store中,创建action函数不在返回一般对象,而是一个函数,该函数中写异步任务,异步任务有结果后,分发一个同步action去真正操作数据

案例:
Count组件,在components/Count下

import React,{Component} from 'react'
import {Decrement,Increment} from '../../redux/count_action';
import store from '../../redux/store'

export default class Count extends Component{

    increment=()=>{
    const {value} = this.number;
    store.dispatch(Increment(value*1));
    }

    decrement=()=>{
        const {value} = this.number;
        store.dispatch(Decrement(value*1));
    }

    IfOddIncrement= ()=>{
      const {value} = this.number;
      if(store.getState() % 2 !==0 ){
          store.dispatch(Increment(value*1));
      }
    }
    IncrementAsync=()=>{
      const {value} = this.number;
     setTimeout(()=>{
        store.dispatch(Increment(value*1));
     },1000)
    }

    render(){
        return(
            <div >
                <h2 >当前的求和的值:{store.getState()}</h2>

                <select ref={ c=> this.number=c } >
                    <option value="1">1</option>
                    <option value="2">2</option>
                    <option value="3">3</option>
                </select>

                <button  onClick={this.increment}>+</button>
                <button onClick={this.decrement}>-</button>
                <button onClick={this.IfOddIncrement}>值为奇数时加</button>
                <button onClick={this.IncrementAsync}>异步加</button>
            </div>
        )
    }
}

redux文件夹下的:
⛄️ action.js


const Increment = (data)=>{
   return {type:'increment',
        data:data
    }
}  

const Decrement = (data)=>{
    return {
        type:'decrement',
        data,
    }
}

export {Decrement,Increment};

⛄️ reducer

// 1.该文件适用于创建一个为Count组件服务的reducer,reducer本质就是一个函数
// 2.reducer函数会接到两个参数,分别为:之前的状态(preState),动作对象(action)
const initState =10;
function reducer(preState=initState,action){
    const {type,data} = action;
    switch(type){
        case 'increment':
            return preState + data
        case 'decrement':
            return preState - data
        default:
            return preState; 
    }
}

export default reducer;

⛄️ store

// 该文件专门用于暴露一个store对象,整个应用只有一个store对象

// 引入createStore,专门用于创建redux中最为核心的store对象
import {createStore} from 'redux'

import reducer from './count_reducer'

const store = createStore(reducer);
console.log(store);

export default  store;

action和reducer可以有多个,但是store只能有一个

6.redux原理图 🔓

7.容器组件和UI组件(傻瓜组件) 🏄

React组件和Redux中store打交道,需要读取store的状态,用于初始化组件的状态,
同时还要监听store状态的改变,当store状态发生改变时,需要更新组件状态,从而驱动组件重新渲染。
一个组件做事情太多,后来就把一个组件拆分成两个组件,让每一个组件只专注做一件事。组件分为容器组件和傻瓜组件,拆分容器组件和傻瓜组件,是设计React组件的一种模式

💖 容器组件:外层组件,是UI组件的父组件
💞 UI组件:让UI组件无状态,UI组件只需要根据props来渲染结果,
👊 使用时,需要引入react-redux库,来连接容器组件和UI组件

案例

🍏 容器组件

// 引入CountUI组件
import CountUI from '../../components/Count/index'
// 引入action对象
import {createIncrementAction,createDecrementAction,createIncrementActionAsync} from '../../redux/count_action'

// 引入connect用于连接容器组件和UI组件
import { connect } from 'react-redux'

function mapStateToProps(state){
    return {
      count:state
    }
};
function mapDispatchToProps(dispatch){
     return{
         increment:(number)=>{
            dispatch(createIncrementAction(number));
         },
         decrement:(number)=>{
            dispatch(createDecrementAction(number));
         },
         incrementAsync:(number,timer)=>{
           dispatch(createIncrementActionAsync(number,timer));
         }
     }
};

const Connect = connect(mapStateToProps,mapDispatchToProps)(CountUI);

export default Connect;

🍏 容器组件简写

// 引入CountUI组件
import CountUI from '../../components/Count/index'
// 引入action对象
import {createIncrementAction,createDecrementAction,createIncrementActionAsync} from '../../redux/count_action'

// 引入connect用于连接容器组件和UI组件
import { connect } from 'react-redux'

const mapStateToProps = state=>({count:state});
 
const mapDispatchToProps=dispatch=>
    ({
         increment:(number)=>{
            dispatch(createIncrementAction(number));
         },
         decrement:(number)=>{
            dispatch(createDecrementAction(number));
         },
         incrementAsync:(number,timer)=>{
           dispatch(createIncrementActionAsync(number,timer));
         }
     });

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

🍎最终写法1:

// 引入CountUI组件
import CountUI from '../../components/Count/index'
// 引入action对象
import {createIncrementAction,createDecrementAction,createIncrementActionAsync} from '../../redux/count_action'

// 引入connect用于连接容器组件和UI组件
import { connect } from 'react-redux'


export default  connect(
  state=>({count:state}),
  dispatch =>
  ({
       increment:(number)=>{
          dispatch(createIncrementAction(number));
       },
       decrement:(number)=>{
          dispatch(createDecrementAction(number));
       },
       incrementAsync:(number,timer)=>{
         dispatch(createIncrementActionAsync(number,timer));
       }
   }))(CountUI);
 mapDispatchToProps可以是
            1.function
            2.对象

🍎最终写法2

// 引入CountUI组件
import CountUI from '../../components/Count/index'
// 引入action对象
import {createIncrementAction,createDecrementAction,createIncrementActionAsync} from '../../redux/count_action'

// 引入connect用于连接容器组件和UI组件
import { connect } from 'react-redux'


export default  connect(
  state=>({count:state}),
 {
   increment:createIncrementAction,
   decrement:createDecrementAction,
   incrementAsync:createIncrementActionAsync
 }

  )(CountUI);

🎡UI组件

import React,{Component} from 'react'

export default class CountUI extends Component{

    increment=()=>{
        const {value} = this.number;
       this.props.increment(value*1);
    };
    decrement=()=>{
        const {value} = this.number;
       this.props.decrement(value*1);
    };
    incrementIfOdd=()=>{
        const {value} = this.number;
        const {count} = this.props;
        if(count % 2 !==0){
            this.props.increment(value*1);
        }
    };
    
    incrementAsync=()=>{
        const {value} = this.number;
        this.props.incrementAsync(value*1,1000);
    };
        render(){
            console.log(this);
            return(
                <div>
                    <h2>当前求和的值为:{this.props.count}</h2>
                    <select ref={c=>this.number=c}>
                        <option value="1">1</option>
                        <option value="2">2</option>
                        <option value="3">3</option>
                    </select>
                    <button onClick={this.increment}>+</button>
                    <button onClick={this.decrement}>-</button>
                    <button onClick={this.incrementIfOdd}>为奇数时加</button>
                    <button onClick={this.incrementAsync}>异步加</button>
                </div>
            )
        }
}

🍬App的组件:(需要传递store,但是可以使用provider)

import React, {Component} from 'react';

import Count from './containers/Count/index'


export default class App extends Component{
    render(){
        return(
            <Count/>
        )
    }
}

🍯 index入口函数
使用react-redux中提供的Provider,可以给所有容器组件传递一个store对象


import ReactDOM from 'react-dom';

import App from './App'

import {Provider} from 'react-redux';

import store from './redux/store'

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

🍉action

import store from './store'

const createIncrementAction = (data)=>{
     return {
           type:'increment',
            data:data
     }
}
// 第二种用了简写
const createDecrementAction = data=>({type:'decrement',data})
// 所谓的异步action,就是指action的值为函数,异步action中一般都会调用action,异步action不是必须要用的
const createIncrementActionAsync = (data,time)=>{
     return ()=>{
          setTimeout(()=>{
               store.dispatch(createIncrementAction(data));
          },time)
     }
}

export {createIncrementAction,createDecrementAction,createIncrementActionAsync};

🍓reducer

// reducer是一个纯函数

const initState = 100;
function reducer(preState=initState,action){
    const {type,data} = action;
    switch(type){
        case  'increment':
            return preState + data;
        case 'decrement':
            return preState - data;
        default:
            return preState;
    }

}
export default reducer;

🍌store

// 引入createStore用于创建store
import {createStore,applyMiddleware} from 'redux'

import reducer from './count_reducer'

// 引入react-thunk用于引入异步action
import thunk from 'redux-thunk'

const store =  createStore(reducer,applyMiddleware(thunk));

export default store;

8.合并容器组件和UI组件 🌈

// 引入action对象
import {createIncrementAction,createDecrementAction,createIncrementActionAsync} from '../../redux/count_action'

// 引入connect用于连接容器组件和UI组件
import { connect } from 'react-redux'

import React,{Component} from 'react'

 class CountUI extends Component{

    increment=()=>{
        const {value} = this.number;
       this.props.increment(value*1);
    };
    decrement=()=>{
        const {value} = this.number;
       this.props.decrement(value*1);
    };
    incrementIfOdd=()=>{
        const {value} = this.number;
        const {count} = this.props;
        if(count % 2 !==0){
            thisReduxVuex状态管理机制

react中redux的介绍与使用

Redux

Redux——详解

Redux 知识点 及 使用案例

redux的基本使用