redux与react-redux学习笔记

一、redux

1、安装 yarn add redux
2、工作原理图解析

在这里插入图片描述

流程步骤:

React Components(客人): react组件想要做什么事情,比如做加法运算

Action Creators(客人选择做菜的方式和选什么菜): 将菜单写好发送给饭店老板(store),action有两个参数 store.dispatch({ type: ‘用哪种方式做’, data: ‘做什么菜’ })

import store from '../../redux/store';
import { createIncrementAction, createDelcrementAction } from '../../redux/count_action';

 inCrement = () => {
        const { value } = this.selectState; // 这是要传入计算的值
        // createIncrementAction这个是从count_action.js中封装好的action方法
     	store.dispatch(createIncrementAction(value)); 
    };

Store(饭店老板): 将菜单发给厨师,同时负责将厨师做好的菜送到客人面前

创建store.js文件

import { createStore } from 'redux';  // 从redux中取出创建仓库函数
import Reducer from './count_reducers'; // 引入加工的reducer
export default createStore(Reducer); // 创建实例同时传入reducer并暴露加工后的reducer值

Reducers(厨师):将菜单上的做菜方式和客人选的菜做好后交给老板,他有两个参数 preState,action

preState:上一个值,也可以直接在形参中初始值

action:接收到客人的action对象,其中有type和data

创建count_reducer.js文件

import { INCREMENT, DELCREMENT } from './constants';

export default function Reducer(initPreState = 0, action) {
    const { type, data } = action;
    switch (type) {
        case INCREMENT:
            return initPreState + data * 1;
        case DELCREMENT:
            return initPreState - data * 1;
        default:
            return initPreState;
    }
}

最终React Components (react组件)希望拿到reducers计算后的值就需要从Store身上获取

const count = store.getState() // 取值
store.getState() // 页面显示

页面更新(订阅):subscribe(注意别写成subscript)

两种方式  
    1、在使用的组件中用ComponentDidMount生命周期中更新
    store.subscribe(()=>{
        this.setState({})
    })
	2、一劳永逸,直接在index.js react入口文件的渲染root根标签外部用store.subscribe包裹,好处是整个root内部的所有文件的store都有实时数据更新的效果
	store.subscribe(() => {
    	root.render(
            <React.StrictMode>
                <App />
            </React.StrictMode>
    	);
	});
3、优化:
1、action常量集

创建constants.js

作用:一般用于reducers中使用,如果需要更改方法直接在constants.js常量集 中修改type类型,

constants.js
export const INCREMENT = 'inCrement'

例如现在在reducers.js中
import { INCREMENT, DELCREMENT } from './constants';

export default function Reducer(initPreState = 0, action) {
    const { type, data } = action;
    switch (type) {
        case INCREMENT:
            return initPreState + data * 1;
        case DELCREMENT:
            return initPreState - data * 1;
        default:
            return initPreState;
    }
}
2、封装创建action方法常量集

创建count_action.js 作用:封装一个action对象

import { INCREMENT } from './constants';
export const createIncrementAction = data => ({ type: INCREMENT, data })

使用的页面需要引入封装好的action方法
import { createIncrementAction } from '../../redux/count_action';
示例:
	 store.dispatch({ type: 'delCrement', data: value });  // 这是没封装前的传参
      store.dispatch(createDelcrementAction(value)); // 使用封装的action
4、传递异步action
action有两种方式传参
第一种:传对象 { type: 'inCrement', data }   同步的
第二种: 传函数 异步的   延迟操作或者接口不喜欢在组件内调用就可以统一写在封装count_action.js集里面
// 引入redux自带的异步中间件  yarn add redux-thunk
// 为啥要下载这个插件? 因为redux异步需要中间件的支持才能传递action,所以这是必经之路。
// 在store.js中导入取出,同时从redux中取出应用中间件函数 applyMiddleware
import { createStore, applyMiddleware } from 'redux';  
import thunk from 'redux-thunk'; 
// 然后在暴露仓库的参数中应用一下,将第三方插件引入,这样整个store仓库就可以接收和返回异步action了
export default createStore(Reducer, applyMiddleware(thunk));

count_action.js   
export const createIncrementAction = data => ({ type: INCREMENT, data });
export const createIncrementAsyncAction = (data, delay) => {
    return dispatch => {
        setTimeout(() => {
            // 由于我们需要的方法其他action已经有了,所以可以直接使用,只需要将我们需要传的参数传入即可
            // 分发有两种写法  
            	// 一种是顶部引入store.js文件
               // store.dispatch(createIncrementAction(data))
               // 第二种是直接在当前return 这个函数体中本身就是在返回store对象,所以可以从形参dispatch直接				传,这样就少写store和少导入store.js文件。
            dispatch(createIncrementAction(data));
        }, delay);
    };
};

组件中使用
导入
import { createIncrementAsyncAction } from '../../redux/count_action';
 asyncCrement = () => {
        const { value } = this.selectState;
        store.dispatch(createIncrementAsyncAction(value, 500));
    };

二、React-redux (facebook)

1、安装 yarn add react-redux
2、工作原理图解析

在这里插入图片描述

容器组件:主要存放容器UI,它自身拥有操作store中的状态和数据的方法api

容器UI:通过this.props获取到容器组件传递过来的store数据进行页面渲染

创建 containers 文件夹并在下面创建 Count 文件 -> index.js (存放容器组件的)

containers -> Count -> index.js
// 引入容器UI
import CountUI from '../../components/Count';
// 取出connect 容器UI 和 容器组件的连接器
import { connect } from 'react-redux';
// 引入封装好的action方法
import {
    createIncrementAction,
    createDelcrementAction,
    createIncrementAsyncAction,
} from '../../redux/count_action';

// 修改store数据   形参是store中的reducer处理后返回给它的数据赋值给count属性,再将count属性传递给子组件,子组件Count就可以通过this.props.count获取到store中的数据了
const mapStateToProps = state => {
    return { count: state };
};

// 分发action到store去修改状态
const mapDispatchToProps = dispatch => {
    return {
        jia: number => dispatch(createIncrementAction(number)),
        jian: number => dispatch(createDelcrementAction(number)),
        jiaAsync: (number, delay) => dispatch(createIncrementAsyncAction(number, delay)),
    };
};

// 连接器需要通过调用两个函数并传入相关参数,
// 第一个函数有两个参数   
// 两个参数都是得传{}形式,一个映射取数据,另一个是映射发送action到store让reducer去修改状态
// 第二个函数是传入一个容器UI从而生成一个容器组件
// 整句代码的意思是传入要加工的action和导入组件并创建暴露出容器组件
export default connect(mapStateToProps, mapDispatchToProps)(CountUI);

在App.jsx 入口文件引入 Count 容器组件用于渲染,为了让store的数据给Count 容器组件内的容器UI都能使用,需要引入并在组件中传递

App.jsx
import React, { Component } from 'react';
import Count from './containers/Count'; // 容器组件
import store from './redux/store'; // 1

export default class App extends Component {
    render() {
        return (
            <div>
                <Count store={store} />  // 1
            </div>
        );
    }
}

component(存放容器UI)

component -> count -> index.jsx  当前容器UI 
inCrement = () => {
        const { value } = this.selectState;
     	// 通过this.props取值
        this.props.jia(value);
    };
3、优化
1、容器组件代码 connect第一个回调传递有两种方式
/* 第一种  用函数变量形式传入
修改store数据   形参是store中的reducer处理后返回给它的数据赋值给count属性,再将count属性传递给子组件,子组件Count就可以通过this.props.count获取到store中的数据了
*/
const mapStateToProps = state => {
    return { count: state };
};

// 分发action到store去修改状态
const mapDispatchToProps = dispatch => {
    return {
        jia: number => dispatch(createIncrementAction(number)),
        jian: number => dispatch(createDelcrementAction(number)),
        jiaAsync: (number, delay) => dispatch(createIncrementAsyncAction(number, delay)),
   };
};
// 创建一个容器组件并链接容器UI   传入两个映射函数变量
export default connect(mapStateToProps, mapDispatchToProps)(CountUI);

/* 第二种   利用react-redux自带的dispatch以及语法优化让代码更简洁,当然也需要看得懂才行
 创建一个容器组件并链接容器UI  
 第一个参数 直接将state表达式写入connect()
 第二个参数 用对象key: value的形式传入,直接调用封装好的action函数就可以,这个参数对象react-redux会自动加上dispatch,所以不用再手动写dispatch */
export default connect(
    state => ({ count: state }), 
    {jia: createIncrementAction,
     jian: createDelcrementAction,
     jiaAsync: createIncrementAsyncAction})
	(CountUI);

2、 引入Provider并在标签中传入store,这样App下的所有组件都可以使用到store的状态和数据了
优化前:
redux还需要在index.js中使用store.subscribe让所有App下的应用使用store都能实时更新,同时哪些容器组件,例如Count中要给自身的容器UI传store还要在容器组件Count中进行引入和传值
缺点:如果多个容器组件那么需要给每个容器组件传store,见下面的ForExample1、ForExample2
App.jsx
import Count from './containers/Count';
import store from './redux/store';
export default class App extends Component {
    render() {
        return (
            <div>
                <Count store={ store } />
                <ForExample1 store={ store } />
                <ForExample2 store={ store } />
            </div>
        );
    }
}


优化后:
项目根目录入口文件  index.js
import store from './redux/store';
import { Provider } from 'react-redux';

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

3、容器组件和容器UI整合版

优化目的:

原本每生成一个容器组件就需要创建容器组件和容器UI文件,1 -> 2,量多文件就翻倍增长

容器UI:components -> Count -> index.jsx

容器组件:contaners -> Count -> index.jsx

优化后代码:

constaners -> Count -> index.jsx
/* 
    四个步骤:
    1、创建容器UI
    2、导入react-redux连接器 connect
    3、连接容器UI创建并生成容器组件暴露出去
    4、连接时传入映射状态和映射操作方法
*/
import React, { Component } from "react";
import { connect } from "react-redux"; // 2
import { createIncrementAction } from "../../redux/count_action";

// 1
class Count extends Component {
  increment = () => {
    this.props.incrementFN(1); 
  };

  render() {
    return (
      <div>
        <h2>当前计算后的值 {this.props.sumCount} </h2>
        <button onClick={this.increment}>1</button>
      </div>
    );
  }
}
// 3 4
export default connect((state) => ({ sumCount: state }), {
  incrementFN: createIncrementAction,
})(Count);

为了让每个新增的对象都拥有唯一的ID,所以可以使用第三方插件nanoid,当然也可以用时间戳或者其他方式

安装命令 yarn add nanoid
如何使用
import { nanoid } from 'nanoid'
直接调用即可  <div> { nanoid() } </div>

combindReducer:可以用对象形式合并多个reducer为一个总reducer,统一发给store进行操作,让redux不再只为一个reducer服务

从redux引入  用对象key:value的形式传入,这样store就可以保存所有状态了 
store.js
import { createStore, applyMiddleware, combineReducers } from 'redux'
import countReducer from '../redux/reducers/count';
import personReducer from '../redux/reducers/person';

export default createStore(
    combineReducers({
        count: countReducer,
        person: personReducer
    })
    , applyMiddleware(thunk));

页面获取store中的状态、

以Person容器组件为例
connect连接器保存着组件的状态,state就是当前容器组件保存在store中的数据,当前容器组件还可以获取其他容器组件的状态。这一过程实现了状态数据共享。
export default connect(
  (state) => ({ renArr: state.person, countSum: state.count }),
  {
    jiayiren: createPersonAction,
  }
)(Person);
4、react redux 开发工具的使用
store.js
/* 下载命令  yarn add redux-devtools-extension
引入  import { composeWithDevTools } from 'redux-devtools-extension'
将 composeWithDevTools 整个react-redux开发工具包裹整个异步action
composeWithDevTools(applyMiddleware(thunk)) */

export default createStore(  
    combineReducers({
        he: countReducer,
        rens: personReducer
    })
    , composeWithDevTools(applyMiddleware(thunk)));

5、将所有容器组件的reducer汇总到一个js文件中,store使用reducer就直接引入这个js文件进行操作

优点:这样如果需要修改reducer或者新增reducer就只需在reducer -> index.js中进行操作,同时store.js中也无需引入大量的reducer,代码更清晰、后期更好维护、更人性化。

reducer -> index.js
在reducer下创建index.js,在该文件中引入所有容器组件的reducer,最终统一暴露一个汇总后的reducer对象

import count from './count';
import person from './person';
// 引入整合reducer方法
import { combineReducers } from 'redux';
export default combineReducers({count, person})

store.js
// 引入统一汇总后的reducer
import reducer from './reducers'
export default createStore(reducer, composeWithDevTools(applyMiddleware(thunk)));
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Redux是一个独立的JavaScript库,用于管理应用程序的状态。它提供了一个可预测的状态容器,可以在整个应用程序中共享。Redux通过单向数据流来管理状态,使得状态的变化变得可控和可预测。 React-ReduxRedux的官方绑定库,它提供了一些与React集成的功能,使得在React应用中使用Redux更加方便。React-Redux提供了一个Provider组件,它可以将Redux store传递给整个应用程序。它还提供了一个connect函数,它可以将Redux store中的状态映射到React组件的props中,使得React组件可以轻松地访问Redux store中的状态。 ### 回答2: Redux是一个用于JavaScript应用程序的状态容器,它提供了一个可预测且可维护的方式来管理应用程序的状态。Redux的核心概念是“单一数据源”,即将整个应用程序的状态存储在单一对象树中,并且任何组件都可以访问和修改该状态树的任意部分。 react-redux是一个与React紧密集成的Redux绑定库。它提供了一组React组件和API,使得使用ReduxReact应用程序中更加容易。 reduxreact-redux之间的关系可以理解为Redux是一种状态管理库,而react-reduxReduxReact之间的纽带。 具体来说,react-redux提供了两种主要的API:Provider和connect。 Provider是一个React组件,允许我们将应用程序的Redux存储连接到React组件树中的所有组件。在Provider组件内部,可以通过store属性传递Redux存储对象,使得所有组件都可以访问该存储。 connect是一个高阶组件,用于将React组件连接到Redux存储中的状态和操作。通过connect,我们可以在React组件中访问Redux状态,以及派发Redux操作。connect本质上是一个函数,它接收一个组件作为参数并返回一个新的连接了Redux存储的组件。 总之,reduxreact-redux之间的区别在于,redux是一个独立的状态管理库,而react-reduxReduxReact之间的桥梁,帮助React应用程序连接到Redux存储,并访问存储中的状态和操作。 ### 回答3: ReduxReact-Redux都是在React项目中使用的JavaScript库。Redux是一个JavaScript状态容器,用于管理应用程序中的所有状态。Redux允许将状态存储在一个单一的地方,以便在整个应用程序中共享该状态。React-ReduxReact的一个库,用于与Redux一起使用,以便在React组件中访问和更新Redux状态。 Redux通过store提供一个单一的状态树,包含了整个应用程序的状态。通过使用store中的action和reducer,Redux可以跟踪状态的所有更改。这可以帮助开发人员更容易地调试和管理代码。但是,使用Redux需要一定的时间和精力来管理各个状态,尤其在较大的代码库中尤其如此。 React-Redux库是Redux的一个扩展,它提供了一组工具来帮助React组件访问和更新Redux状态。通过提供Provider组件,React-Redux使得Redux存储的状态可以传递到整个应用程序中的所有组件。通过使用connect函数和mapStateToProps和mapDispatchToProps参数,React-Redux允许开发人员将Redux状态映射到React组件中。这样,开发人员就可以根据需要将Redux状态作为props传递给组件,并且可以更方便地将状态更改传递回Redux store。 总之,ReduxReact提供了一个易于管理的状态储存架构,以帮助应用程序开发人员管理和跟踪应用程序状态。React-Redux是一组工具,它使开发人员可以更方便地在React组件中使用Redux,从而帮助开发人员更快地开发应用程序。两者的区别在于Redux是包含整个应用程序状态的状态容器,而React-Redux则是提供了一组工具,以帮助开发人员更方便地在React组件中使用Redux状态。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值