组件间数据更新,可以不写 callback 吗?【玩转 React Hooks】

顺手就是一套 callback

业务场景

在最新一期的需求中,我需要在所有的购买入口,添加”阅读购买须知”的模块。

“阅读购买须知”的模块主要包括两部分内容:购买须知按钮和提示文案。

提交购买时,也需要增加对应的校验:是否已经进行了阅读操作。

  • 如果未操作,给出提示且不能进行下一步操作;

  • 如果已操作,可以继续下一步操作。

UI 展示效果

组件间数据更新,可以不写 callback 吗?【玩转 React Hooks】

组件化设计

按照代码复用的设计理念,我将”购买须知”模块进行了组件化设计。

下单操作,需要获取”购买须知”组件返回的”阅读状态”的值,于是我顺手写了一个 callback 函数,返回最新的”阅读状态”的值。

“购买须知”组件

这个组件主要包括两个部分:

1、”购买须知”按钮,同时需要在按钮右侧展示提示文字,提示文字根据”阅读状态”不同,展示内容也不同:

  • 未操作时,提示”请单击购买须知”;
  • 已操作时,提示”可继续下一步操作”。

2、”购买须知”展示弹窗,展示具体的内容。弹窗有取消和确定两个操作,这两个操作会为”阅读状态”设置不同的值:

  • 确定操作,将”阅读状态”的值设置为1-已操作;
  • 取消操作,将”阅读状态”的值设置为2-未操作。
/**
 * @description 购买须知
 */
import React, { useState } from 'react';
import { Button } from 'antd';

const PurchaseNotes = props => {
  const { callback } = props;
  const [visible, setVisible] = useState(false);
  const [tip, setTip] = useState({});

  /**
   * 根据阅读状态获取展示文字
   * @param {number} status 阅读状态 1-通过 2-不通过
   */
  const getShowTip = status => {
    let healthInformStatusObjAll = {
      1: {
        text: '可继续下一步操作',
        className: 'node-block',
      },
      2: {
        text: '请单击购买须知',
        className: 'node-red',
      },
    };
    let show = healthInformStatusObjAll[status] || {};
    return show;
  };

  /**
   * 公共处理方法
   */
  const commonStatusHandle = status => {
    callback && callback(status);
    const tipObj = getShowTip(status);
    setTip(tipObj);
  };

  /**
   * 操作-关闭
   */
  const cancel = () => {
    setVisible(false);
    commonStatusHandle(2);
  };

  /**
   * 操作-确定
   */
  const ok = () => {
    setVisible(false);
    commonStatusHandle(1);
  };

  return (
    <div>
    <div className={`node ${tip.className}`}>
  <Button
className="mr20"
onClick={() => {
  setVisible(true);
}}
  >
  购买须知
  </Button>
{tip.text ? <div>{tip.text}</div> : null}
  </div>
  <Modal title="购买须知" visible={visible} onOk={ok} onCancel={cancel}>
  <div className="text-left">这是购买须知的内容</div>
  </Modal>
  </div>
 );
};

export default PurchaseNotes;

页面引入组件

1、在购买页面引入组件,并通过 callback 函数设置”阅读状态”值。并在提交操作中加入校验。

/**
 * @description Demo
 */
import React, { useState } from 'react';
import { Button, message } from 'antd';
import PurchaseNotes from './PurchaseNotes';

const Demo = () => {
  const [status, setStatus] = useState(null);

  /**
   * 购买须知回调函数
   */
  const notesCallback = status => {
    setStatus(status);
  };

  /**
   * 提交操作
   */
  const submit = () => {
    // 提交前的校验
    if (status !== 1) {
      return message.error('请单击购买须知');
    }
  };

  return (
    <div>
    <PurchaseNotes callback={notesCallback} />
    <Button type="primary" onClick={submit}>
    提交
    </Button>
    </div>
  );
};

export default Demo;

2、未操作”购买须知”时的展示效果

组件间数据更新,可以不写 callback 吗?【玩转 React Hooks】

3、已操作”购买须知”时的展示效果

组件间数据更新,可以不写 callback 吗?【玩转 React Hooks】

直接将 setStatus 作为 prop

使用 callback 的目的也是拿到 PurchaseNotes 组件中 status 的值,然后在页面中进行赋值操作。

那直接将 setStatus 作为 prop 传递到 PurchaseNotes 组件中岂不省去了”回调赋值”这一步。

页面传值

将 setStatus 赋值函数 作为 prop 传递到子组件 PurchaseNotes中。

const [status, setStatus] = useState(2);
......
<PurchaseNotes setStatus={setStatus} />

组件赋值

直接使用 setStatus 进行赋值操作。

const { setStatus } = props;
......
/**
 * 公共处理方法
 */
const commonStatusHandle = status => {
  setStatus && setStatus(status);
  ......
};

这样一来,就省了一步”回调赋值”的操作。

总结

虽说这里只是做了简单的一小步改变,但是如果重复的地方多,也能节省了一大波的重复代码。

偶尔,这类”小技巧”容易被开发者忽略,我也是因为”每个页面都得写一遍 callback”枯燥,才想办法找替代方案。

小技巧,大改观。—— 叶一一

显然,成果就是亮点。


作者介绍

非职业「传道授业解惑」的开发者叶一一。

《趣学前端》、《CSS畅想》等系列作者。华夏美食、国漫、古风重度爱好者,刑侦、无限流小说初级玩家。

如果看完文章有所收获,欢迎点赞👍 | 收藏⭐️ | 留言📝。

原文链接:https://juejin.cn/post/7243413934766440507 作者:叶一一

(0)
上一篇 2023年6月12日 上午10:15
下一篇 2023年6月12日 上午10:25

相关推荐

发表回复

登录后才能评论