组件间数据更新,可以不写 callback 吗?【玩转 React Hooks】
顺手就是一套 callback
业务场景
在最新一期的需求中,我需要在所有的购买入口,添加"阅读购买须知"的模块。
"阅读购买须知"的模块主要包括两部分内容:购买须知按钮和提示文案。
提交购买时,也需要增加对应的校验:是否已经进行了阅读操作。
- 如果未操作,给出提示且不能进行下一步操作;
- 如果已操作,可以继续下一步操作。
UI 展示效果
组件化设计
按照代码复用的设计理念,我将"购买须知"模块进行了组件化设计。
下单操作,需要获取"购买须知"组件返回的"阅读状态"的值,于是我顺手写了一个 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、未操作"购买须知"时的展示效果
3、已操作"购买须知"时的展示效果
直接将 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畅想》等系列作者。华夏美食、国漫、古风重度爱好者,刑侦、无限流小说初级玩家。
如果看完文章有所收获,欢迎点赞👍 | 收藏⭐️ | 留言📝。
- 点赞
- 收藏
- 关注作者
评论(0)