Redux及React-Redux概述

Posted 橘猫吃不胖~

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Redux及React-Redux概述相关的知识,希望对你有一定的参考价值。

React Redux概述

Redux概述

1 设计思想

Redux是javascript的状态管理器。可以和React配合,也可以和Vue配合。

  • Redux将应用中的所有状态存储在store中(store是全局的),里面存在一个状态树state tree。
  • store本身不能修改自己,它通过store.dispatch派发相应的行为(action)给用户定义的reducer函数,来生成新的store(更新store)
  • 其他组件通过订阅store中的state来刷新自己的视图
  • 强调:Redux设计是基于“发布——订阅”模式

2 三大原则

  • 整个应用有且只有一个store
  • state是只读的,修改state只能通过派发action来实现(将action派发给reducer纯函数1来实现)。因此开发时第一步是编写reducer函数。
  • 单一数据源2的设计便于状态(数据)的统一管理,便于react组件之间的数据传递

缺点:
(1)需要手动引入store,不方便
(2)需要手动订阅,不方便

3 使用方法

1、安装模块:安装redux

npm install redux

2、通过createStore生成store:Redux 提供createStore这个函数,用来生成 Store。

import createStore from "react";
function reducer() 

let store = createStore(reducer);

注意:
(1)reducer是一个纯函数,由用户定义
(2)其返回值是一个store对象,该对象有以下方法可调用:

方法含义
store.getState()获取状态
store.dispatch()派发action
store.subscribe()订阅store中state的变化

3、定义reducer函数
reducer是一个纯函数,由用户定义,它的返回值取决于参数。

它需要两个参数,分别是state和action,state是旧的状态,不可直接修改,而是需要根据action.type不同,来生成新的state并返回。

4、更新state
通过store.dispatch()来派送不同的action,在reducer中通过action.type来判断action的类型,根据类型执行不同的更新操作。

5、订阅store中的state

this.unSubscribe = store.subscribe(() => 
    // 获取新的state
)

强调:store.subscribe()函数的返回值为函数,用于取消订阅

注:没有派送任何action时,也会有一个action的原因:store为了拿到初始值,会自动派发一个action

手撕代码:手写实现createStore函数功能的代码

function myCreateStore(reducer) 
    let state;
    const listeners = [];

    // 返回最新的state
    function getState() 
        return state;
    

    // 派发action
    function dispatch(action) 
        state = reducer(state, action);
        listeners.forEach(listener => listener());
    

    // 订阅:返回取消订阅函数
    function subscribe(listener) 
        listeners.push(listener);
        return function () 
            const index = listeners.indexOf(listener);
            listeners.splice(index, 1);
        
    

    // 获取state默认值
    dispatch(type: "橘猫吃不胖---@@redux/INTTg.u.b.z.n.n");
    // 返回store,一个对象
    return 
        getState,
        dispatch,
        subscribe
    


export default myCreateStore;

4 bindActionCreators

redux 提供了 bindActionCreators 功能,将action的函数与store.dispatch进行绑定。绑定后就不用store.dispatch直接派发action。

用法:

let/const 变量名 =  bindActionCreators(action函数名,store.dispatch)

5 【案例】实现计数器

1、效果展示:

2、编写store.js文件。在该文件中实现了生成State、创建store和生成reducer函数。

import createStore from "redux"; // 生成Store
// 定义常量
export const ADD = "ADD";
export const MINUS = "MINUS";
// 创建reducer函数,接收两个参数
// state:旧的状态,不可以直接修改,而是根据action.type的不同生成新的state并返回
// action:不同的动作,在本例中指ADD和MINUS
function reducer(state = count: 0, action) 
    // 首次加载后,即使没有action,控制台也输出了该信息
    // 这时因为store为了拿到state的初始值count:0,会自动派发一次actiontype: "@@redux/INIT1.s.m.m.c.n"
    // Redux内部使用“发布——订阅”模式
    console.log(action);
    // 对action进行判断
    switch (action.type) 
        case ADD:
            return count: state.count + 1;
            break;
        case MINUS:
            return count: state.count - 1;
            break;
        default:
            return state;
    

// 创建store对象
let store = createStore(reducer);
export default store; // 导出

3、编写Counter.js文件,在该文件中实现了页面的效果,在这里有3中写法:
(1)普通方法实现

import React from "react";
// 导入store对象,通过该对象派发action
import store from "../redex/store";

// 导入actions
import bindActions from "../redex/actions";

// 创建类组件,实现页面效果
class Counter extends React.Component 
    constructor(props) 
        super(props);
        this.state = 
            // 将store中的最新的state赋给当前组件的state
            // getState():获取最新的state tree
            // count是在store.js文件中定义的,初始值为0
            number: store.getState().count,
        
    

    componentDidMount()  // 页面加载完成后执行该函数
        // 对store的state进行订阅
        // store.subscribe可以实现订阅,同时该方法会返回一个函数,用于取消订阅
        // 设置this.unSubScribe为当前类的属性,表示可以取消订阅的对象
        this.unSubScribe = store.subscribe(() => 
            this.setState(
                number: store.getState().count
            )
        )
    

    componentWillUnmount() 
        // 在组件卸载时取消订阅
        this.unSubScribe();
    

    render() 
        return (
            <div>
                /*页面上显示当前状态下的数值*/
                <p>this.state.number</p>
                /*当点击“加1”按钮时派发行为action:ADD*/
                <button onClick=() => store.dispatch(type: "ADD")>1</button>
                &nbsp;&nbsp;
                <button onClick=() => store.dispatch(type: "MINUS")>1</button>
            </div>
        );
    


export default Counter;

(2)使用bindActionCreators实现:

import React from "react";
// 导入store对象,通过该对象派发action
import store from "../redex/store";
import bindActionCreators from "redux";

// 导入actions
import bindActions from "../redex/actions";

//定义action函数
function add() 
    return type: "ADD"


function minus() 
    return type: "MINUS"


//进行绑定
const bindAdd = bindActionCreators(add, store.dispatch);
const bindMinus = bindActionCreators(minus, store.dispatch);

// 创建类组件,实现页面效果
class Counter extends React.Component 
    constructor(props) 
        super(props);
        this.state = 
            // 将store中的最新的state赋给当前组件的state
            // getState():获取最新的state tree
            // count是在store.js文件中定义的,初始值为0
            number: store.getState().count,
        
    

    componentDidMount()  // 页面加载完成后执行该函数
        // 对store的state进行订阅
        // store.subscribe可以实现订阅,同时该方法会返回一个函数,用于取消订阅
        // 设置this.unSubScribe为当前类的属性,表示可以取消订阅的对象
        this.unSubScribe = store.subscribe(() => 
            this.setState(
                number: store.getState().count
            )
        )
    

    componentWillUnmount() 
        // 在组件卸载时取消订阅
        this.unSubScribe();
    

    render() 
        return (
            <div>
                /*页面上显示当前状态下的数值*/
                <p>this.state.number</p>
                <button onClick=bindAdd>1</button>
                &nbsp;&nbsp;
                <button onClick=bindMinus>1</button>
            </div>
        );
    


export default Counter;

(3)将bindActionCreators抽离到单独的文件actions实现,这样可以使代码的结构清晰,因此actions.js代码如下:

import bindActionCreators from "redux";
import store from "./store";

//定义action函数
function add() 
    return type: "ADD"


function minus() 
    return type: "MINUS"


const actions = add, minus;

const bindActions = bindActionCreators(actions, store.dispatch);

export default bindActions;

Counter.js文件代码如下:

import React from "react";
// 导入store对象,通过该对象派发action
import store from "../redex/store";
// 导入actions
import bindActions from "../redex/actions";

// 创建类组件,实现页面效果
class Counter extends React.Component 
    constructor(props) 
        super(props);
        this.state = 
            // 将store中的最新的state赋给当前组件的state
            // getState():获取最新的state tree
            // count是在store.js文件中定义的,初始值为0
            number: store.getState().count,
        
    

    componentDidMount()  // 页面加载完成后执行该函数
        // 对store的state进行订阅
        // store.subscribe可以实现订阅,同时该方法会返回一个函数,用于取消订阅
        // 设置this.unSubScribe为当前类的属性,表示可以取消订阅的对象
        this.unSubScribe = store.subscribe(() => 
            this.setState(
                number: store.getState().count
            )
        )
    

    componentWillUnmount() 
        // 在组件卸载时取消订阅
        this.unSubScribe();
    

    render() 
        return (
            <div>
                /*页面上显示当前状态下的数值*/
                <p>this.state.number</p>
                <button onClick=bindActions.add>1</button>
                <button onClick=bindActions.minus>1</button>
            </div>
        );
    


export default Counter;

最后在App.js文件中使用<Counter/>组件就可以看到效果。

React-Redux概述

1 简介

(1)是redux官方给出的react绑定库
(2)不是react内置的,使用时需要安装
(3)通常和redux结合使用
(4)方便react组件读取store中的数据,并且向store中分发action来更新数据

2 使用过程

1、安装

npm install redux
npm install react-redux

2、Provider和connect
(1)Provider:将store传递给所有的子组件

<Provider store=用户定义的store>
    <App/>
</Provider>

(2)connect:高阶组件(传入一个组件,它会返回新的加工后的组件)

connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])	

[mapStateToProps]:函数,用于监控Redux store的变化,一旦store的值发生改变,该函数就会被调用,将redux store的state合并到组件的props中
[mapDispatchToProps]:将action合并到组件的props中
[mergeProps], [options]参数可以不写,用默认值即可

示例代码:

connect(mapStateToProps,mapDispatchToProps)(组件名)

含义:将store中的state和store派发的action都合并到给定组件的props属性中

3 【案例】实现计数器

1、效果展示

2、编写store.js文件,在该文件中定义了reducer函数,生成了store,代码如下:

import createStore from "redux";

export const ADD = "ADD";
export const MINUS = "MINUS";

function reducer(state = count: 0, action) 
    switch (action.type) 
        case ADD:
            return count: state.count + 1
        case MINUS:
            return count: state.count - 1
        default:
            return state;
    


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

3、编写action.js文件,在该文件中定义了两个函数,返回了action.type,代码如下:

function add() 
    return type: "ADD";


function minus() 
    return type: "MINUS"


const actions = add, minus;

export default actions;

4、编写counter.js文件,在该文件中实现了效果,代码如下:

import React from "react";
import connect from "react-redux";
import actions from "../actions/action";

class Counter extends React.Component 
    render() 
        return (
            <>
                <p>Count:this.props.count</p>
                <br/>
                <button onClick=this.props.add>Count++</button>
                &nbsp;&nbsp;&nbsp;
                <button onClick=this.props.minus>Count--</button>
            </>
        );
    


const mapStateToProps = (state) => state; // 函数,监视store中的state的变化

const mapDispatchToProps =  //对象:保存的action
    ...actions


// 将store中的state和需要store派发的action绑定到组件中
export default connect(mapStateToProps, mapDispatchToProps)(Counter);

5、修改App.js中代码,具体如下:

import './App.css';
import Counter from "./components/counter";

function App() 
    return (
        <div className="App">
            <header className="App-header">
                <Counter/>
            </header>
        </div>
    );


export default App;

6、修改index.js文件代码如下:

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import Provider from "react-redux";
import store from "./react-redux/store";

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

  1. 纯函数: 函数的返回值取决于参数,和外部的其他代码没有关系 ↩︎

  2. 单一数据源:所有的数据都存储在store中 ↩︎

以上是关于Redux及React-Redux概述的主要内容,如果未能解决你的问题,请参考以下文章

react-redux的connect()方法

从 react-redux 迁移到 redux-toolkit 后使用 configureStore 传递初始状态的最佳方法

React-Redux 知识点 及 实现数据共享案例

通过 React-Redux 进行地理定位

React-Redux的使用

antdesign怎么集合react-redux对input控件进行初始化赋值