2)react-redux抽离redux

为什么用react-redux?

  1. redux与react组件的代码耦合度太高
  2. 编码不够简洁

基本概念

React-Redux将所有组件分成两大类

 UI组件

a.只负责 UI 的呈现,不带有任何业务逻辑

b.通过props接收数据(一般数据和函数)

c.不使用任何 Redux 的 API

d.一般保存在components文件夹下

容器组件

a.负责管理数据和业务逻辑,不负责UI的呈现

b.使用 Redux 的 API

c.一般保存在containers文件夹下

相关API

1.Provider

让所有组件都可以得到state数据

<Provider store={store}>
    <App />
  </Provider>

2.connect()

用于包装 UI 组件生成容器组件

import { connect } from 'react-redux'
  connect(
    mapStateToprops,
    mapDispatchToProps
  )(Counter)

3.mapStateToprops()

将外部的数据(即state对象)转换为UI组件的标签属性
  const mapStateToprops = function (state) {
   return {
     value: state
   }
  }

4.mapDispatchToProps()

将分发action的函数转换为UI组件的标签属性

简洁语法可以直接指定为actions对象或包含多个action方法的对象

下载包 npm install --save react-redux

优化redux:根据 React-Redux组件分类思想,将app.jsx从上一篇的redux内抽离出来

// app.jsx
import { connect } from "react-redux";
// 引入action内的方法
import { increment, decrement } from "../redux/actions";
// 引入容器组件
import counter from "../components/counter";

export default connect(
  (state) => {
    // state为store内的count值 即0
    console.log(state, "state");
    // 将state状态传给counter组件
    return { count: state };
  },
  // 将increment,decrement方法传给counter
  { increment, decrement }
)(counter);

// counter.js内
// 导入 React 模块
import React, { Component } from "react";

import propTypes from "prop-types";


// 暴露并创建react类
export default class App extends Component {
  static propTypes = {
    count: propTypes.number.isRequired,
    increment: propTypes.func.isRequired,
    decrement: propTypes.func.isRequired,
  };
  addCountFn = () => {
    this.props.increment(this.select.value * 1);
  };
  delCountFn = () => {
    this.props.decrement(this.select.value * 1);
  };
  incrementOddFn = () => {
    const { count } = this.props;
    if (count % 2 === 1) {
      this.props.increment(this.select.value * 1);
    }
  };
  incrementAsyncFn = () => {
    setTimeout(() => {
      this.props.increment(this.select.value * 1);
    }, 1000);
  };
  render() {
    const { count } = this.props;
    return (
      <div>
        <h2>click {count} times</h2>
        <select ref={(select) => (this.select = select)}>
          <option value="1">1</option>
          <option value="2">2</option>
          <option value="3">3</option>
        </select>
        &nbsp;
        <button onClick={this.addCountFn}>+</button>&nbsp;
        <button onClick={this.delCountFn}>-</button>&nbsp;
        <button onClick={this.incrementOddFn}>increment if odd</button>&nbsp;
        <button onClick={this.incrementAsyncFn}>increment async</button>
      </div>
    );
  }
}

// index.js
import React from "react";
import { createRoot } from 'react-dom/client';
import { Provider } from "react-redux";

import store from './redux/store'
import App from "./containers/app";

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

上一篇问题:reducers.js如何暴露多个模块

​// reducers.js
import { COMMENT_ADD, COMMENT_DEL, COMMENT_INIT, INCREMENT, DECREMENT } from "./action-types";
import { combineReducers } from 'redux'
const initCommentData = []

function comments (state = initCommentData, actions) {
  switch (actions.type) {
    // 添加方法
    case COMMENT_ADD:
      return [actions.data, ...state]
    // 删除方法
    case COMMENT_DEL:
      return state.filter((comment, index) => index !== actions.data)
    // 初始化评论
    case COMMENT_INIT:
      return actions.data
    // 默认
    default:
      return state
  }
}

function counter (state = 0, action) {
  switch (action.type) {
    case INCREMENT:
      return state += action.data
    case DECREMENT:
      return state -= action.data
    default:
      return state
  }
}

export default combineReducers(
  {
    comments,
    counter
  }
)

暴露多个模块后,相应的组件 也要做修改

// app.jsx
import React, { Component } from "react";
import { connect } from "react-redux";
import PropTypes from "prop-types";

import Add from "../../components/commentAdd/commentAdd";
import List from "../../components/commentList/commentList";
import { commentAdd, commentDel, commentAsync } from "../../redux/actions";
import "./app.css";

class App extends Component {
  static propTypes = {
    commentList: PropTypes.array.isRequired,
    commentAdd: PropTypes.func.isRequired,
    commentDel: PropTypes.func.isRequired,
    commentAsync: PropTypes.func.isRequired,
  };
  componentDidMount() {
    const { commentAsync } = this.props;
    commentAsync();
  }
  render() {
    const { commentList, commentAdd, commentDel } = this.props;

    return (
      <div id="app">
        <div>
          <header className="site-header jumbotron">
            <div className="container">
              <div className="row">
                <div className="col-xs-12">
                  <h1>请发表对React的评论</h1>
                </div>
              </div>
            </div>
          </header>
          <div className="container">
            <Add commentAdd={commentAdd} />
            <List commentList={commentList} commentDel={commentDel} />
          </div>
        </div>
      </div>
    );
  }
}


export default connect((state) => 
// 此处为reducers修改后调整
({ commentList: state.comments }), 
{
  commentAdd,
  commentDel,
  commentAsync
}
)(App);
// store.js 存储 状态变量

import { configureStore } from '@reduxjs/toolkit'

import reducers from './reducers'

// 根据comments函数创建store对象

const store = configureStore({ reducer: reducers })
console.log(store, 'store');
export default store
 


 

redux如何处理异步操作???

redux-thunk处理异步操作_FF_XM的博客-CSDN博客

redux基本概念

redux初体验(问题记录)_FF_XM的博客-CSDN博客

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值