news 2026/4/23 16:10:07

RN + TypeScript 项目越写越乱?如何规范架构?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
RN + TypeScript 项目越写越乱?如何规范架构?

@[toc]

如果你在 RN 项目里用了 TypeScript,但还是经常遇到下面这些情况,那你大概率不是一个人:

  • 业务一多,代码开始到处飞,找逻辑像在翻垃圾堆
  • hooks 套 hooks,useEffect 里再调 useEffect,自己都不敢改
  • 类型文件一堆,但和真实实现经常对不上
  • 新人一来就问:“这个状态到底在哪儿改的?”

这篇文章不是教你“TypeScript 怎么写”,而是教你:
在 RN 项目里,TypeScript 怎么和架构一起用,才能不失控。

一、为什么 RN + TS 项目特别容易“写乱”?

先说一个结论:

项目乱,不是因为 TypeScript,而是“职责边界不清 + 状态乱流”。

1. 业务增长,逻辑开始横向扩散

最常见的场景:

  • 页面里写请求
  • hook 里也写请求
  • redux 里再写一套
  • utils 里还有一份“备用逻辑”

结果是:
一个需求改 4 个地方,还不一定改全。

2. Hooks 层级复杂,本来是解耦,最后变成“黑盒”

你可能写过类似这样的代码:

functionusePageLogic(){constdata=useFetch()constresult=useProcess(data)useEffect(()=>{doSomething(result)},[result])}

问题不是 hooks 多,而是:

  • hooks 里混了业务规则
  • hooks 之间有隐式依赖
  • 调试时根本不知道是哪一层出问题

3. 类型与实现分离,最后谁都不信类型

常见症状:

  • interface 写得很全
  • 实际接口返回偷偷多字段 / 少字段
  • any 越用越多
  • 最后 TS 只剩“自动补全工具”的作用

二、一个能长期维护的 RN + TS 项目结构

先给你一个推荐结构总览,这是我在中大型 RN 项目里反复验证过的。

src/ ├── domain/ // 业务模型 & 业务规则 ├── service/ // API / SDK / 数据来源 ├── hooks/ // 可复用 hooks ├── store/ // 全局状态 ├── ui/ // 纯 UI 组件 ├── pages/ // 页面(只组装,不写重逻辑) ├── utils/ └── types/

接下来我们逐层拆。

三、domain 层:业务规则的“唯一入口”

domain 是整个项目的核心。

你应该在 domain 里放什么?

  • 业务实体(User、Order)
  • 业务规则(状态转换、校验)
  • 与 UI、网络无关的逻辑

示例:用户领域模型

// domain/user.tsexportinterfaceUser{id:stringname:stringrole:'admin'|'user'}exportfunctionisAdmin(user:User){returnuser.role==='admin'}

关键点:

  • domain 不 import RN、API、store
  • domain 只关心“业务正确性”

四、service 层:所有“数据来源”的统一出口

service 只做一件事:

把外部世界的数据,变成 domain 能用的数据。

示例:请求用户接口

// service/userService.tsimport{User}from'@/domain/user'exportasyncfunctionfetchUser():Promise<User>{constres=awaitfetch('/user')returnres.json()}

不要在页面里直接 fetch。

五、hooks 层:封装“状态 + 行为”,但不写业务规则

一个非常重要的原则:

hooks = orchestration,不是 business logic。

示例:useUser

// hooks/useUser.tsimport{useEffect,useState}from'react'import{fetchUser}from'@/service/userService'import{User}from'@/domain/user'exportfunctionuseUser(){const[user,setUser]=useState<User|null>(null)useEffect(()=>{fetchUser().then(setUser)},[])returnuser}

如果你发现 hook 里开始写if (role === 'admin')
那说明:逻辑该下沉到 domain 了。

六、UI 层:彻底“无脑”的组件

UI 组件只负责:

  • 接 props
  • 渲染
  • 触发回调

示例:用户卡片

type Props = { name: string onPress: () => void } export function UserCard({ name, onPress }: Props) { return ( <Pressable onPress={onPress}> <Text>{name}</Text> </Pressable> ) }

UI 层不 import hooks、不 import service。

七、页面(Page):只做“组装”

页面是“最脏但最轻”的一层。

export function UserPage() { const user = useUser() if (!user) return null return ( <UserCard name={user.name} onPress={() => {}} /> ) }

页面:

  • 可以用 hook
  • 可以用 store
  • 但不写核心逻辑

八、全局状态方案怎么选?

这是 RN 项目里非常容易踩坑的一点。

Redux Toolkit

适合:

  • 状态多
  • 多页面共享
  • 对可预测性要求高

优点:

  • 规范
  • DevTools 强

缺点:

  • 样板代码略多

Zustand

适合:

  • 中小项目
  • 状态简单
  • 希望写得快
constuseStore=create(set=>({count:0,inc:()=>set(state=>({count:state.count+1}))}))

Recoil

适合:

  • 状态依赖复杂
  • 类似图结构

但心里要有数:生态和长期维护要评估。

九、TypeScript 在 RN 项目的最佳实践

1. 类型从 domain 开始

不要一上来就写:

typeProps=any

类型应该从业务模型流出。

2. 禁止“到处定义重复类型”

统一出口:

exporttype{User}from'@/domain/user'

3. 不要为了 TS 而 TS

有些地方允许不完美:

constref=useRef<any>(null)

关键在于:核心业务链路一定要有类型。

十、常见反模式(请尽量避免)

1. 滥用 useEffect 做状态管理

useEffect(()=>{setA(calcB(b))},[b])

这种写多了,状态会完全失控。

2. 一个 hook 管一切

usePageLogic()

内部 500 行代码,没人敢碰。

3. domain 被 UI 污染

import{Alert}from'react-native'

一旦 domain import RN,架构就开始塌。

十一、真实项目里的收益

在真实 RN 项目中,用这套结构后:

  • 新需求平均开发时间 ↓ 30%+
  • Bug 定位明显更快
  • 新人 1~2 天能独立改需求
  • TS 不再是“摆设”

最后的总结

如果你只记住一句话:

RN + TypeScript 的核心不是“写类型”,而是“让结构帮你兜住复杂度”。

TypeScript 是放大器:

  • 架构好 → TS 越用越爽
  • 架构乱 → TS 只会更痛苦
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/23 14:15:50

​多店运动场馆预约小程序、我们这样开发!

多店运动场馆预约小程序、我们这样开发&#xff01; 网球馆、羽毛球馆、健身房、瑜伽馆、普拉提馆等运动场馆筹备需要准备的东西之定制小&#x1f34a;序来啦[派对R] &#x1f4f1;​支持场地预约、教务管理、次卡、储值、优惠券、营销活动、财务报表、扫码门禁、到店指引、团购…

作者头像 李华
网站建设 2026/4/23 14:16:04

【Dify元数据最佳实践】:构建高可用Agent工具注册体系的4个关键步骤

第一章&#xff1a;Agent 工具注册的 Dify 元数据定义在构建基于 Dify 的智能 Agent 系统时&#xff0c;工具注册是实现功能扩展的核心环节。每一个注册工具都必须附带一组结构化的元数据&#xff0c;用于描述其能力、输入输出格式以及调用方式。这些元数据由 Dify 平台解析并用…

作者头像 李华
网站建设 2026/4/23 15:00:04

使用蚁剑连接一句话木马远程控制小皮

首先我们启动小皮&#xff1a;事先写好一句话木马并以php的格式保存将木马文件放到小皮目录下在蚁剑中添加数据&#xff0c;输入url和连接密码&#xff0c;测试连接后发现连接成功此时我们便可以通过蚁剑访问本机文件了关于127.0.0.1127.0.0.1 是 IPv4 协议中预留的本地回环地址…

作者头像 李华
网站建设 2026/4/23 13:31:34

混合检索中Dify查询优化的8个致命误区,90%工程师都踩过坑!

第一章&#xff1a;混合检索中Dify查询优化的核心挑战在构建基于大语言模型与知识库协同的智能应用时&#xff0c;Dify平台通过混合检索机制融合关键词匹配与向量语义搜索&#xff0c;以提升查询结果的相关性。然而&#xff0c;在实际应用中&#xff0c;该机制面临多项核心挑战…

作者头像 李华
网站建设 2026/4/23 13:31:51

【大厂都在用的测试方法论】:基于Agent的Dify用例自动生成体系

第一章&#xff1a;基于Agent的Dify用例自动生成体系概述在人工智能与自动化测试深度融合的背景下&#xff0c;基于Agent的Dify用例自动生成体系应运而生。该体系通过部署轻量级智能代理&#xff08;Agent&#xff09;&#xff0c;实现对Dify平台业务逻辑的动态感知与测试需求解…

作者头像 李华
网站建设 2026/4/23 13:31:41

视频帧提取效率低?你必须掌握的Dify底层存储秘技

第一章&#xff1a;视频帧提取效率低&#xff1f;根源剖析与优化必要性在处理视频分析、目标检测或机器学习训练数据准备时&#xff0c;视频帧提取是关键前置步骤。然而&#xff0c;许多开发者面临提取速度慢、资源占用高、输出质量不稳定等问题。这些问题不仅拖慢整体流程&…

作者头像 李华