react dispatch_基于 React、TS 的聊天室 monorepo 实战-深圳网站优化推广公司

react dispatch_基于 React、TS 的聊天室 monorepo 实战

ba56a7efc647eac99a98d31180abac97.png

最近在思考如何编写高质量的 React 项目,刚好接到聊天室的需求,于是决定写一篇关于 React、TS 的实战教程,采用 monorepo+lerna 管理包。如何关注代码质量与规范的同时,快速实现需求。

接下来,带着大家快速开发一个 Web 版聊天室。心急的小伙伴可以直接看源码

PS:该教程面向有一定 React、TS 、Node 经验的前端开发者,通过学习您将获得:

  • UI 组件库搭建
  • Lerna + monorepo 的开发模式
  • 基于 React hook 的状态管理
  • http://socket.io 在客户端和服务端的应用

目标

实现多人在线聊天,可发送文本、表情、图片。

接着来看下我们要实现的页面长什么样子:

0954a4af8e88a83854d80d048ce4b2a7.png

开发计划与项目初始化

通过需求分析后,制定如下开发计划:

9af1202e8de92f8976506bdaeb9441bc.png

基础配置

基础配置是通过自研脚手架快速搭建的,其中包括:

  1. 添加 eslint、prettier、husky 用于代码规范、git 提交规范
  2. 添加 Lerna 配置,yarn workspaces
  3. 在 packages 目录建立 @im/component@im/app@im/server
这里说明下,个人习惯在用 TS 时,将 prettierprintWidth 设置为 120 (标准是 80)。目的是,能用一行代码表达的,绝不用两行,代码格式化造成的也不行。

接着分别介绍每个包的具体细节

UI 库

秉承快速开发的节奏,直接采用 create-react-app cli 初始化 UI 库。命令如下:

  1. 初始化 React+TS 环境
npx create-react-app component --typescript
  1. 初始化 Storybook
cd component
npx -p @storybook/cli sb init --story-format=csf-ts
  1. 添加 storybook addons
{
  addons: [
    '@storybook/preset-create-react-app',
    '@storybook/addon-viewport', // 手机预览效果
    '@storybook/addon-notes/register-panel', // API 文档
    '@storybook/addon-actions',
    '@storybook/addon-links',
  ],
};

最终以这种模式去规范组件库的开发(PS:没有文档的组件库,不叫组件库):

6ea1cc17c32449fcd53f688abcbe4447.png

客户端

APP 的开发采用我们最熟悉的模式,直接用 create-react-app 初始化环境。

npx create-react-app app --typescript

整个聊天室项目采用的是多包管理模式,所以在开发时我们会直接通过 lerna link 命令来创建软连接,因此可以不必通过发布包来完成依赖的使用。

但这里要注意的是,由于 create react app 命令生成的项目中 babel 配置是忽略编译 node_modules 的。所以,不得不覆盖其 webpack 配置

这里简单通过 react-app-rewired 到方式来达成目的,但并不是最佳实践。

服务端

这里,服务端的代码,仅作为辅助演示的作用,因此暂不考虑健壮性。标配 ts-nodenodemonexpress 即可满足需求。

启动命令如下:

nodemon --watch 'src/**/*.ts' --ignore 'src/**/*.spec.ts' --exec 'ts-node' src/index.ts

核心实现

至此,基本的环境以及搭建完毕。接下来讲下聊天室核心实现逻辑

大家可以用个 TODO 的方式进行开发,比如:

f60e28f7b4a4a1076af3238f409c156d.png

把需求拆分成若干个任务,每个任务关联到一个 TODO,并以此规范 git commit。

消息组件设计

虽然项目是基于 Material-UI 开发的,但考虑到业务带来的差异性,组件库可能需要高度定制,故直接采用全量导出的方式来使用基础 UI 组件。

聊天室用到比较多是消息流组件,比如:纯文本消息组件,纯图片消息组件,系统消息组件,推荐组件等。

├── MessageBase.tsx # 包含头像、反向显示的基础消息组件
├── MessageMedia.tsx # 图片、音频等
├── MessageSystem.tsx # 系统消息
├── MessageText.tsx # 文本组件
├── __stories__ # 文档相关
│   ├── Demo.tsx
│   ├── Message.stories.tsx
│   ├── README.md
│   └── img.jpg
└── index.tsx

主要的设计思路:

  1. 以组合的方式开发组件
  2. 保持组件 API 一致性
  3. 尽可能简单,不过度设计

目前需要实现的消息组件比较简单,具体实现,可以看源码。这里主要传达的是文件组织方式和基本设计思路。

数据流设计

先来看下,React hook 出现后,前端可以如何更优雅地共享状态

export const ChatContext = React.createContext<{
  state: typeof initialState;
  dispatch: (action: Action) => void;
}>({
  state: initialState,
  dispatch: () => {},
});

export const useChatStore = () => React.useContext(ChatContext);

export function ChatProvider(props: any) {
  const [state, dispatch] = React.useReducer(reducer, initialState);
  const value = { state, dispatch };
  return <ChatContext.Provider value={value}>{props.children}</ChatContext.Provider>;
}
  1. 通过 React.createContext 创建 context
  2. 通过 React.useReducer 管理 reducer,生成 state 与 dispatch
  3. 通过 React.useContext 获取状态源

这样,我们就可以很方便的维护局部或全局状态。至于是否要将所有的状态都放到根状态树里以及 domain 数据是否需要状态化,就是另外一个故事了,这里就留给读者自己去深究。

接着我们来设计一个聊天室所需的数据结构:

interface State {
  messages: Message[]; // 数组的方式存储所有消息,保持有序
  members: { [id: string]: Member }; // map 的形式存储当前聊天室所有用户,便于查询
}

数据尽可能地保持简单,比如一个 message 的结构可以是这样:

interface Message {
  id: string;
  type: MESSAGE_TYPE; // 消息类型,用于渲染不用的消息组件
  userId: string; // 发送消息的用户标识
  content: object; // 根据消息组件类型收敛的数据结构
}

MESSAGE_TYPE 消息类型枚举,用于与消息流组件隐射一一对应,以及 socket 消息发送时的 type 数据。建议可以在 @im/helper 里统一维护这类的常量。

interface Member {
  id: string;
  avatar: string;
  name: string;
}

通过消息中的 userId 去 members 获取对应用户数据来渲染头像和用户昵称等。

按以上的约定基本可以满足一个简单的聊天室了。另外,如果组件层级比较多,组件粒度拆得比较细的话,在不考虑业务组件复用的情况下,可以引入一些共享状态,如:currentUserId、socket、activeTool 等,可有效避免父子组件状态传达,但这里需要开发者自行权衡复用性。

客户端 Socket

  1. 组件挂载完成后,建立 socket 链接,并保存当前 socket 实例,卸载后记得断开连接。
React.useEffect(() => {
  const socket: SocketIOClient.Socket = io('http://localhost:3002');
  dispatch({ type: Type.INSERT_SOCKET, payload: socket });
  return () => {
    socket.close();
  };
}, [dispatch]);
  1. 通过以下方式通知服务端,比如用户加入聊天室
state.socket.emit('add user', username);
  1. 监听服务端事件,比如用户发送消息
React.useEffect(() => {
  if (!state.socket) {
    return;
  }
  state.socket.removeAllListeners();

  state.socket.on('login', handleLogin);
  state.socket.on('user joined', handleUserJoin);
  state.socket.on('user left', handleUserLeft);
  state.socket.on('new message', handelNewMessage);
}, [state.socket, handleLogin, handleUserJoin, handelNewMessage, handleUserLeft]);

服务端 Socket

这是一个 socket 官方的 demo,比较简单。不考虑其他的场景,这样就可以了!

import express from 'express';
import socket from 'socket.io';
const server = require('http').createServer(app);
const io = socket(server);

server.listen(port);

io.on('connection', socket => {
  // 处理接收的新消息
  socket.on('new message', data => {
    // 通知其他客户端
    socket.broadcast.emit('new message', {
      id: v4(),
      username: socket.username,
      userId: socket.userId,
      message: data.message,
      type: data.type,
    });
  });
});

客户端和服务端的 socket 已经完成通信,贴代码总是很累的,具体细节参看源码。

QA

这一节我通过问答的方式来快速过一下开发聊天室中可能遇到的问题:

  1. 如何实现表情发送

简单的表情可以当做文本来处理,如果需要考虑兼容性的话,可以用图片。这里不做具体展开

  1. 如何滚动到最新消息
React.useEffect(() => {
  if (lastMessage) {
    // 获取最后一个消息元素
    lastMessage.scrollIntoView();
  }
}, [lastMessage]);

总结

快速的带大家实现了一个简易的 Web 版聊天室,从需求分析,到代码规范组织,在到数据流设计,最后介绍了 socket 在客户端和服务端的应用,想必大家对如何快速开发聊天室也有了大致的认识。希望本教程有帮助到大家,谢谢。最近在思考如何编写高质量的 React 项目,刚好接到聊天室的需求,于是决定写一篇关于 React、TS 的实战教程,采用 monorepo+lerna 管理包。如何关注代码质量与规范的同时,快速实现需求。

weixin_39531780 CSDN认证博客专家 CSDN认证企业博客
码龄7年 暂无认证
135
原创
-
周排名
213万+
总排名
24万+
访问
等级
354
积分
35
粉丝
37
获赞
0
评论
246
收藏
私信
为什么被折叠? 到【灌水乐园】发言
前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值

相关内容推荐

合肥网站制作 晨飞网络可靠西安动画制作公司网站手绘头像制作网站在线兴安网站制作石景山网站制作和推广制作独立网站阿里云企业网站制作音乐网站首页图片制作网站制作需要如何学习网站后台制作难度为什么要制作音乐网站洛阳网站制作准备哪些台州企业网站制作公司小视频网站的制作小学网站制作视频永川网站制作推广罗湖制作网站价格网站logo制作方法大连网站运营制作方案深圳沙井网站制作公司丰县网站设计制作电脑海报制作网站忻州关键词网站制作钢之家网站制作小玩具网站制作教程精品课音乐在线网站怎么制作表白h5制作网站酉阳手机版网站制作晋城网站建设制作慈溪企业网站制作价格360度全景制作网站亦庄公司网站制作公司韶关网站制作推广电话深圳网站制作newnet彩票网站开发制作软件桐乡制作网站用什么工具湖北省会计网站制作网站制作不能忽略的细节网站flash动画怎么制作企石网站建设制作哪家好明星网站制作美食学习网站设计制作心得低价网站建设制作惠州仲恺电商网站制作设计网站需要用什么制作工具衡水网站制作代理价格沧州企业网站设计制作怎样制作海报网站沈阳鑫鸿云网站制作优势制作网站正在维护中网站制作如何添加滚动字幕转账支票制作网站标准化网站制作哪儿好素材网站制作头像玄武租房网站制作忻州企业网站制作电话dw制作相册类型网站南京网站制作的公司哪家好一点梁春分海报制作网站邵阳专业简历制作网站武侯网站的制作公司吉林网站建设模板制作沙头有效的网站制作丹阳网站制作教程答题卷制作的网站网站专题制作 公司制作数据加载图标网站在线ps制作手机版网站凡科网网站制作如何制作超链接网站flash动画怎么制作光明营销型网站制作价格吴中区电商网站制作哪家专业制作钓鱼网站的费用北京律所网站制作昌平禅城网站制作公司网站制作的团队介绍内容大型企业网站制作流程怎么制作花店网站无锡网站制作无锡立威云商标杆午夜影视网站制作蜘蛛的小制作网站靖江最优的网站制作公司日立网站制作小玩具金坛废品回收网站制作耳环手工制作网站网站开发制作策略制作网站排名葛金泉网邯郸网站制作公司排名数学网站制作头像建材网站制作分解在线制作ico网站源码360网站制作手工制作网上订餐网站个人小软件制作网站制作自己的网站多少钱免费学习视频制作的网站建委网站制作网站制作素材稀有温柔北京网站制作产品dw中如何制作音乐网站线路板支付网站制作义乌温州市微网站制作多少钱制作教育网站论文底线素材网站制作怎么制作有图片的网站义乌大连网站制作需要多少钱定海区网站制作企业自助免费网站制作跟踪电影网站制作广东专注网站制作品牌性价比高的网站制作一般多少钱网站制作要学哪些语言孝感微网站制作浦口区企业型网站建设制作电子请柬制作免费网站UI网站制作蛋糕奥斯卡电影网站制作潍坊网站制作哪有厦门网站制作专注乐云seo保定石家庄网站制作个人网站制作的代码初中生节水网站的制作齐齐哈尔网站制作哪家有实力文字照片制作网站广州网站制作一般多少钱企业邮箱网站制作冰淇淋怀化微网站制作微信动态表情包制作网站四季青网站制作网站制作三站拍拍网站制作壁纸广州网站制作皆赞乐云践新制作美食网站的意义何在百度百科医院网站制作画皮网站制作起泡网站制作项目描述滨海开发区手机网站制作蒙古网站制作ppt制作高逼格表白网站安阳网站制作推广制作手机端网站模板制作一个网站教程视频软件个人作品展示网站制作模板旅行网站制作冰淇淋地铁图标网站制作网站制作推广优化苏州网站的制作公司上海复旦大学自考网站制作广元小程序网站制作多少钱网站cms系统制作且看网站制作企业独立网站制作哪个新年祝福视频制作网站比较好傻瓜网站制作冰淇淋网站制作器google手机版更合网站搭建制作如何制作cms电影网站怀化网站制作联系电话网站专题制作教学长宁网站制作企业谈谈网站首页的制作流程app网站制作方案flash是网站制作软件吗长虹网站制作雪糕如何制作吸引力的网站制作官方网站多少钱怎么推广网站制作服务北京企业门户网站制作网站下拉菜单制作实例网站制作困难吗网站制作私单红孩儿网站制作巩义网站制作价格花衣裳网站制作花都制作网站制作课件免费的网站传奇网站制作奶茶南京网站页设计制作将网站制作成快捷方式莱芜网站设计制作山东婚庆网站制作如何制作www网站网站制作首行缩进在哪东北虎网站制作表格西乡媒体网站制作定陶县网站制作网页设计网站制作流程网站制作与网页设计的社会实践网站制作计算机术语网站广告动图制作大同租房网站制作百思买网站制作干花制作一个新闻网站有什么困难动态图片制作网站免费下载选择网站制作公司网站制作图片边框做法象山龙岗综合网站制作都有哪些东莞网站制作奶茶俱乐部网站制作表格传奇网站制作工具器

合作伙伴

深圳网站优化推广公司

龙岗网络公司
深圳网站优化
龙岗网站建设
坪山网站建设
百度标王推广
天下网标王
SEO优化按天计费
SEO按天计费系统