使用 react-redux 实现组件的状态管理和数据通信

1. 实现效果

上面是Count组件,下面是Flag组件。

Count组件中,点击点击+1按钮,数值加一,点击清零按钮,数值清零,同时数值传递给Flag组件同步显示。

Flag组件中,点击login可以切换为true,点击logout切换为false,同时将状态传递给Count组件同步显示。

2. 安装依赖包

npm install react-redux redux redux-thunk redux-devtools-extension

3. 文件结构

使用了redux,需要在UI组件外套一层容器组件。由于是父子关系,容器组件通过props向里层的UI组件传递参数,将容器组件放在containers文件夹下。

使用redux,需要单独创建redux文件夹,包括actions文件夹和reducers文件夹,还有向外暴露常量的constant.jsstore.js

4. 详细代码

1. Count 组件

(1)组件定义

通过class定义的是UI组件,向外暴露的是容器组件容器组件通过propsUI组件传递状态方法

// src/containers/Count/index.jsx
import React, { Component, Fragment } from 'react';
import { connect } from 'react-redux';
import { add, clear } from '../../redux/actions/count';

// UI组件
class Count extends Component {
    add = () => {
        // 通知redux
        this.props.add(1);
    };
    clear = () => {
        this.props.clear();
    };
    render() {
        return (
            <Fragment>
                <h2>当前求和为:{this.props.count}</h2>
                <h3>当前Flag:{this.props.flag ? 'true' : 'false'}</h3>
                <button onClick={this.add}>点击+1</button>
                <button onClick={this.clear}>清零</button>
            </Fragment>
        );
    }
}

// 暴露容器组件
export default connect(
    // 1.状态
    state => ({ count: state.sum, flag: state.flagState }),
    // 2.方法
    { add, clear }
)(Count);

(2)创建action

该文件用于创建action对象。

// src/redux/actions/count.js
// 为Count组件创建action对象

// 引入常量
import { ADD, CLEAR } from '../constant';

// 创建加一action对象的函数
export const add = data => ({
    type: ADD,
    data,
});

// 创建清零action对象的函数
export const clear = data => ({
    type: CLEAR,
    data,
});

(3)reducer

该文件用于判断type的类型,加工数据。

// src/redux/reducers/count.js
// 为Count组件创建一个reducer
// reducer接收两个参数:之前状态的preState,动作对象action

import { ADD, CLEAR } from '../constant.js';

// 设定初始状态
const initState = 0;

export default function addReducer(preState = initState, action) {
    // 从action中获取type和data
    const { type, data } = action;
    // 根据type决定如何加工数据
    switch (type) {
        case ADD:
            return preState + data;
        case CLEAR:
            return 0;
        // 初始化动作
        default:
            return preState;
    }
}

2. Flag 组件

(1)组件定义

// src/containers/Flag/index.jsx
import React, { Component, Fragment } from 'react';
import { connect } from 'react-redux';
import { login, logout } from '../../redux/actions/flag';

class Flag extends Component {
    login = () => {
        this.props.login();
    };
    logout = () => {
        this.props.logout();
    };

    render() {
        return (
            <Fragment>
                <h2>当前Flag:{this.props.flag ? 'true' : 'false'}</h2>
                <h3>当前求和为:{this.props.count}</h3>
                <button onClick={this.login}>login</button>
                <button onClick={this.logout}>logout</button>
            </Fragment>
        );
    }
}

export default connect(state => ({ flag: state.flagState, count: state.sum }), { login, logout })(
    Flag
);

(2)创建action

// src/redux/actions/flag.js
// 为Flag组件创建action对象

// 引入常量
import { LOGIN, LOGOUT } from '../constant';

// 创建加一action对象的函数
export const login = data => ({
    type: LOGIN,
    data,
});

// 创建加一action对象的函数
export const logout = data => ({
    type: LOGOUT,
    data,
});

(3)reducer

// src/redux/reducers/flag.js
//  reducer接收两个参数:之前状态的preState,动作对象action

import { LOGIN, LOGOUT } from '../constant.js';

// 设定初始状态
const initState = false;

export default function addReducer(preState = initState, action) {
    const { type } = action;
    switch (type) {
        case LOGIN:
            return true;
        case LOGOUT:
            return false;
        default:
            return preState;
    }
}

3. 汇总所有 reducer

所有的组件的reducer要汇总到一个文件中,并向外暴露redux中存放的状态对象

// src/redux/reducers/index.js
// 汇总所有的reducer

import { combineReducers } from 'redux';

import sum from './count';
import flagState from './flag';

export default combineReducers({
    sum,
    flagState,
});

4. 常量文件

// src/redux/constant.js
export const LOGIN = 'login';
export const LOGOUT = 'logout';

export const ADD = 'add';
export const CLEAR = 'clear';

5. store

引入汇总后的rudecer,暴露store

// src/redux/store.js
// 整个文档只有一个store对象

import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import allRudecers from './reducers';
import { composeWithDevTools } from 'redux-devtools-extension';

// 暴露store
export default createStore(allRudecers, composeWithDevTools(applyMiddleware(thunk)));

6. 项目入口文件 index.js

引入store,并将<App /><Provider store={store}></Provider>包裹,这样<App />下所有的组件都能接收到store了。

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.jsx';
import store from './redux/store';
import { Provider } from 'react-redux';

ReactDOM.render(
    // Provider包裹App,目的:让App所有的后代容器组件都能接收到store
    <Provider store={store}>
        <App />
    </Provider>,
    document.getElementById('root')
);

欢迎在我的博客上访问:
https://lzxjack.top/

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

火星飞鸟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值