React——Redux

Redux

在上一篇博客里,如果两个子节点要共享数据,就必须把公共数据放到最近公共祖先里,redux的作用就是单独有一块区域可以用来存放公共数据,可以看成全局变量
**redux将所有数据存储到树中,且树是唯一的。**每一个结点都会有一个值

Redux基本概念

  • store:存储树结构。
  • state:维护的数据,一般维护成树的结构。
  • reducer:对state进行更新的函数,每个state绑定一个reducer。传入两个参数:当前state和action,返回新state。
  • action:一个普通对象,存储reducer的传入参数,一般描述对state的更新类型。
  • dispatch:传入一个参数action,对整棵state树操作一遍。

代码示例:(维护一个结点)

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import { configureStore } from '@reduxjs/toolkit';

//只有根结点的树 action是一个对象(字典)
//这个type和value是我们传参时自己在字典里定义的 可以任意取
const f1 = (state = 100, action) => {
  switch(action.type){
    case 'add':
      return state + action.value;
    case 'sub':
      return state - action.value;
    default:
      return state
  }
};

//存储树结构
const store = configureStore({
  reducer: f1
});

//在每次dispatch之后输出
store.subscribe(() => {console.log(store.getState())});

//树只有一个参数type 传入add对所有结点操作一遍
store.dispatch({type: "add", value: 1});
store.dispatch({type: "sub", value: 7});
store.dispatch({type: "add", value: 5});
store.dispatch({type: "add", value: 1});

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    
  </React.StrictMode>
);

代码示例:(维护两个结点)

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import { configureStore } from '@reduxjs/toolkit';
import { combineReducers } from '@reduxjs/toolkit';

//第一个结点
const f1 = (state = 100, action) => {
  switch(action.type){
    case 'add':
      return state + action.value;
    case 'sub':
      return state - action.value;
    default:
      return state
  }
};

//第二个结点
const f2 = (state = "", action) => {
  switch(action.type){
    case 'concat':
      return state + action.character;
    default :
      return state;
  }
}

//父结点 组合f1和f2的方法就是将两个结点作为父结点字典里的对象
const f3 = (state = {}, action) => {
  return{
    f1: f1(state.f1, action),
    f2: f2(state.f2, action),
  }
}

// 或者用API实现组合
// const f3 = combineReducers({
//   f1; f1,
//   f2: f2,
// })

//存储树结构
const store = configureStore({
  reducer: f3
});

//在每次dispatch之后输出
store.subscribe(() => {console.log(store.getState())});

//树只有一个参数type 传入add对所有结点操作一遍
store.dispatch({type: "add", value: 1}); //{f1: 101, f2: ""}
store.dispatch({type: "sub", value: 7}); //{f1: 94, f2: ""}
store.dispatch({type: "concat", character: "abc"}); //{f1: 94, f2: "abc"}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    
  </React.StrictMode>
);

React-Redux基本概念

  • Provider组件:用来包裹整个项目,其store属性用来存储redux的store对象。
  • connect(mapStateToProps, mapDispatchToProps)函数:用来将store与组件关联起来。
  • mapStateToProps(函数):每次store中的状态更新后调用一次,用来更新组件中的值。
  • mapDispatchToProps(对象):组件创建时调用一次,用来将store的dispatch函数传入组件。

安装

npm i redux react-redux @reduxjs/toolkit

举例:
App组件下面两个子节点 Number组件(number.jsx)和String组件(string.jsx)
state树包含number和string两个结点,在文件index.js中
在这里插入图片描述
首先,如何在Number组件访问number的值,在String组件访问string的值?
connect函数:用来将store与组件关联起来。mapStateToProps
app.jsx

import React, { Component } from 'react';
import Number from './number';
import String from './string';


class App extends Component {
    state = {  } 
    render() { 
        return (
            <React.Fragment>
                <Number />
                <String />
            </React.Fragment>
        );
    }
}
 
export default App;

number.jsx

import React, { Component } from 'react';
import {connect} from 'react-redux';


class Number extends Component {
    state = {  } 
    render() { 
        console.log(this.props);//{number: 100, dispatch: ƒ}
        return (
            <React.Fragment>
                <h1>Number:</h1>
                <div>{this.props.number}</div>
            </React.Fragment>
        );
    }
}

//要访问state的number的值,并命名为number
const mapStateToProps = (state, props) => {
    return{
        number: state.number,
    }
}

//将值绑定到组件上 也就是Number的props有了一个参数number
export default connect(mapStateToProps)(Number);

string.jsx

import React, { Component } from 'react';
import { connect, Provider } from 'react-redux';

class String extends Component {
    state = {  } 
    render() { 
        return (
            <React.Fragment>
                <h1>String</h1>
                <div>{this.props.string}</div>
            </React.Fragment>
            
        );
    }
}

const mapStateToProps = (state, props) => {
    return{
        string: state.string,
    }
};
 
export default connect(mapStateToProps)(String);

index.js

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import { configureStore } from '@reduxjs/toolkit';
import { combineReducers } from '@reduxjs/toolkit';
import { Provider } from 'react-redux';
import App from './components/app';

//第一个结点
const f1 = (state = 100, action) => {
  switch(action.type){
    case 'add':
      return state + action.value;
    case 'sub':
      return state - action.value;
    default:
      return state
  }
};

//第二个结点
const f2 = (state = ":", action) => {
  switch(action.type){
    case 'concat':
      return state + action.character;
    default :
      return state;
  }
}

//父结点 组合f1和f2的方法就是将两个结点作为父结点字典里的对象
const f3 = (state = {}, action) => {
  return{
    number: f1(state.f1, action),
    string: f2(state.f2, action),
  }
}

// 或者用API实现组合
// const f3 = combineReducers({
//   f1; f1,
//   f2: f2,
// })

//存储树结构
const store = configureStore({
  reducer: f3
});

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

其次,如何在Number组件里修改string的值,在String组件里修改number的值?mapDispatchToProps
在Number组件内实现一个按钮“添加”,每次点击添加,在string后面加一个字符y,在String组件内实现两个按钮,sub按钮点击number减2,add按钮点击number加3
number.jsx

import React, { Component } from 'react';
import {connect} from 'react-redux';


class Number extends Component {
    state = {  } 

    handleClick = () => {
        this.props.concat('y'); //这个concat也就是绑定的concat
    }

    render() { 
        return (
            <React.Fragment>
                <h1>Number:</h1>
                <div>{this.props.number}</div>
                <button onClick={this.handleClick}>添加</button>
            </React.Fragment>
        );
    }
}

//要访问state的number的值,并命名为number
const mapStateToProps = (state, props) => {
    return{
        number: state.number,
    }
}

const mapDispatchToProps = {
    concat :(c) => { //实现将c添加concat到string
        return{
            type: "concat", //因为string里有这个concat
            character: c, //character和type都是string字典里定义的
        }
    }
};

//将值绑定到组件上 也就是Number的props有了一个参数number
//将concat函数绑定到组件上
export default connect(mapStateToProps, mapDispatchToProps)(Number);

string.jsx

import React, { Component } from 'react';
import { connect } from 'react-redux';

class String extends Component {
    state = {  } 

    handleClickLeft = () =>{
        this.props.sub(3);
    }

    handleClickRight = () =>{
        this.props.sub(2);
    }

    render() { 
        return (
            <React.Fragment>
                <h1>String</h1>
                <div>{this.props.string}</div>
                <button onClick={this.handleClickLeft}>Sub</button>
                <button onClick={this.handleClickRight}>Plus</button>
            </React.Fragment>
            
        );
    }
}

const mapStateToProps = (state, props) => {
    return{
        string: state.string,
    }
};

const mapDispatchToProps = {
    sub : (n) => {
        return{
            type: "sub",
            value: n,
        }
    },
    add : (n) => {
        return{
            typr: "add",
            value: n,
        }
    }
}
 
export default connect(mapStateToProps, mapDispatchToProps)(String);

实现效果:(原谅我不会做动图)
在这里插入图片描述
点击添加五次:
在这里插入图片描述
点击Sub一次
在这里插入图片描述

项目地址:

redux-app

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值