【react框架之dvajs】搞懂这些,dva的数据流你就可以随意拿捏了

dva 是开发的 React 应用框架,将React-Router,Redux及异步操作Redux-saga三个 React 工具库包装在一起,简化了 API,让开发 React 应用更加方便和快捷。

数据变化的时机

数据的改变发生通常是通过用户交互行为或者浏览器行为(如路由跳转等)触发的,当此类行为会改变数据的时候可以通过 dispatch 发起一个 action,如果是同步行为会直接通过 Reducers 改变 State ,如果是异步行为(副作用)会先触发 Effects 然后流向 Reducers 最终改变 State,所以在 dva 中,数据流向非常清晰简明。

在这里插入图片描述

所以得出这个公式 =======》 dva = React-Router + Redux + Redux-saga

数据流模式

  • 同步数据
    在这里插入图片描述
  • 异步数据
    在这里插入图片描述

现在看看在dva里面怎么处理公共的数据仓库

实现效果

请添加图片描述
需要提醒的,项目已经安装好这三个工具,不用再安装。

核心概念

  • State:一个对象,保存整个应用状态
  • ViewReact 组件构成的视图层
  • Action:一个对象,描述事件
  • connect 方法:一个函数,绑定 StateView
  • dispatch 方法:一个函数,发送 ActionState

代码实现

  • routes/IndexPage.js的逻辑
import React from "react";
import {
    
     connect } from "dva";
import styles from "./IndexPage.css";
import PropTypes from "prop-types";
import {
    
     Button, Space } from "antd";

function IndexPage(props) {
    
    
  const {
    
    
    username,
    count,
    addCount,
    decCount,
    addCountAsync,
    minusCountAsync,
  } = props;

  return (
    <div className={
    
    styles.normal}>
      <h1 className={
    
    styles.title}>Yay! Welcome to dva!</h1>
      <div className={
    
    styles.welcome} />

      <div className="demo-container">
        {
    
    username}
        <p>{
    
    count}</p>
        <Space>
          <Button onClick={
    
    addCount} type="primary">
            Add
          </Button>
          <Button type="primary" danger onClick={
    
    decCount}>
            Minus
          </Button>

          <Button onClick={
    
    addCountAsync}>Add async 2s</Button>
          <Button onClick={
    
    minusCountAsync} danger>
            Add async 2s
          </Button>
        </Space>
      </div>
    </div>
  );
}

IndexPage.defaultProps = {
    
    
  username: "admin",
  count: 10,
};

IndexPage.propTypes = {
    
    
  username: PropTypes.string,
  count: PropTypes.number,
};

const matStateToProps = (state) => {
    
    
  return {
    
    
    count: state.products.count,
  };
};

const mapDispatchToprops = (dispatch) => {
    
    
  return {
    
    
    addCount: () => dispatch({
    
     type: "products/addCount" }),
    decCount: () => dispatch({
    
     type: "products/minusCount" }),
    addCountAsync: () => dispatch({
    
     type: "products/addCountAsync" }),
    minusCountAsync: () => dispatch({
    
     type: "products/minusCountAsync" }),
  };
};

export default connect(matStateToProps, mapDispatchToprops)(IndexPage);
  • models/products.js的逻辑
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
export default {
    
    
  namespace: "products",
  state: {
    
    
    count: 0,
    lists: [
      {
    
     name: "dva", id: 1 },
      {
    
     name: "antd", id: 2 },
    ],
  },
  // 同步更新的方法
  reducers: {
    
    
    delete(state, {
    
     id }) {
    
    
      return {
    
    
        ...state,
        lists: state.lists.filter((item) => item.id !== id),
      };
    },
    addCount(state) {
    
    
      return {
    
     ...state, count: state.count + 1 };
    },
    minusCount(state) {
    
    
      return {
    
     ...state, count: state.count - 1 };
    },
  },

  effects: {
    
    
    // *addCountAsync(action, effects) {
    
    
    //   const { put, select, call } = effects;
    //   const data = yield select();
    //   console.log("我被点击了");
    //   yield call(delay, 2000);
    //   yield put({ type: "addCount" });
    // },

    // 设置不同类型的监听器,监听器类型有takeLatest, takeEvery, throttle, debounce
    addCountAsync: [
      function* (action, effects) {
    
    
        const {
    
     put, call } = effects;
        yield call(delay, 2000);
        yield put({
    
     type: "addCount" });
      },
      {
    
    
        type: "takeLatest",
      },
    ],
    *minusCountAsync(action, effects) {
    
    
      const {
    
     put, call } = effects;
      yield call(delay, 2000);
      yield put({
    
     type: "minusCount" });
    },
  },
};

**注意:**effects里面的getor方法默认的监听模式是takeEvery模式,也就是每次出发都会见听到,如下图请添加图片描述
如果我们要更改模式,getor方法就要改写成如下

之前的,默认是takeEvery

*addCountAsync(action, effects) {
    
    
  const {
    
     put, select, call } = effects;
   const data = yield select();
   console.log("我被点击了");
   yield call(delay, 2000);
   yield put({
    
     type: "addCount" });
 },

特定的监听模式

addCountAsync: [
 function* (action, effects) {
    
    
    const {
    
     put, call } = effects;
    yield call(delay, 2000);
    yield put({
    
     type: "addCount" });
  },
  {
    
    
    type: "takeLatest",
  },
]

是不是很简单了,直接简化了之前单独引入三个工具库的代码,操作方便不少。

附上第二个实例的效果及代码 请添加图片描述

  • routes/Products .js
import React from "react";
import {
    
     connect } from "dva";
import ProductList from "../components/ProductList";

const Products = (props) => {
    
    
  const {
    
     products, deleteProduct } = props;
  return (
    <>
      <h2>List of Products</h2>
      <ProductList onDelete={
    
    deleteProduct} products={
    
    products} />
    </>
  );
};

const mapStateToProps = (state) => {
    
    
  return {
    
    
    products: state.products.lists,
  };
};

const mapDispatchToProps = (dispatch) => {
    
    
  return {
    
    
    deleteProduct: (id) => {
    
    
      dispatch({
    
     type: "products/delete", id });
    },
  };
};

export default connect(mapStateToProps, mapDispatchToProps)(Products);
  • components/ProductList .js
import React from "react";
import PropTypes from "prop-types";
import {
    
     Table, Popconfirm, Button } from "antd";

const ProductList = ({
     
      onDelete, products }) => {
    
    
  const columns = [
    {
    
    
      title: "Name",
      dataIndex: "name",
    },
    {
    
    
      title: "Actions",
      render: (text, record) => {
    
    
        return (
          <Popconfirm title="Delete?" onConfirm={
    
    () => onDelete(record.id)}>
            <Button>Delete</Button>
          </Popconfirm>
        );
      },
    },
  ];
  return <Table dataSource={
    
    products} columns={
    
    columns} rowKey="id" />;
};

ProductList.defaultProps = {
    
    
  products: [],
};

ProductList.propTypes = {
    
    
  onDelete: PropTypes.func.isRequired,
  products: PropTypes.array.isRequired,
};

export default ProductList;

在这里插入图片描述

扫描二维码关注公众号,回复: 17524508 查看本文章

猜你喜欢

转载自blog.csdn.net/qq_27702739/article/details/143570919