跳到主要内容

快速开始

安装依赖并配置主题宿主后,即可使用组件。以下示例演示亮暗主题的接入。

环境要求

支持矩阵严格来自 package.json#peerDependencies,本仓直接验证的版本是 React Native 0.86.3 + React 19.2.3:

依赖支持范围本仓验证版本
react-native>=0.86.00.86.3
react>=19.2.3 <20.0.019.2.3
react-native-gesture-handler>=3.0.0 <4.0.03.1.0
react-native-reanimated>=4.5.2 <4.7.04.6.0
react-native-worklets>=0.11.0 <0.13.00.12.1
react-native-reanimated-carousel>=5.0.0 <6.0.05.0.0
react-native-safe-area-context>=55.7.x
react-native-svg>=1515.15.x
@sbaiahmed1/react-native-blur>=46.0.x
  • Node.js ^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0(与 package.json#engines 逐字一致;本仓 .nvmrc 固定 v24.13.0)、Yarn 4
  • TypeScript 6
仅支持新架构,RN 下限 0.86

本库面向 RN 0.86+ 新架构(Fabric + TurboModules),支持 react-native-reanimated@4.5/4.6 + react-native-worklets@0.11/0.12。旧架构(Bridge)与 RN 0.85 及更低版本不在支持范围 —— 发布 contract 是 >=0.86.0,不封顶;当前验证基线为 RN 0.86.3

安装依赖

1. 装本库

yarn add @unif/react-native-design

2. 装 peer dependencies

peer 依赖需要完整配置

本库不打包下列依赖,宿主工程必须自行安装并完成原生侧配置。缺任一,Metro 打包或运行时就会报 Unable to resolve module / Cannot find module

yarn add react-native-svg \
react-native-gesture-handler \
react-native-reanimated \
react-native-worklets \
react-native-safe-area-context \
react-native-reanimated-carousel \
@sbaiahmed1/react-native-blur

iOS 装完原生包后,在 ios/ 目录执行 bundle exec pod install

版本范围见上方环境要求表格,唯一事实来源是 package.json#peerDependencies

Worklets 需要宿主自备 Babel / Metro

react-native-worklets 的 Babel 插件与 Metro transformer 由宿主工程提供,不随本库分发。宿主必须装上与自身 RN 版本匹配的 @babel/core@react-native/babel-preset@react-native/metro-config;本仓验证的是 RN 0.86.3 与对应 0.86.3 工具链,否则 worklet 编译会静默降级或直接报错。

RNRC 5.0.0 与 Gesture Handler 3 的 peer 冲突

本包要求 Gesture Handler 3.x,但 react-native-reanimated-carousel@5.0.0 发布的 peer 范围是 >=2.9.0 <3.0.0 —— 与本包的 >=3.0.0 <4.0.0 完全没有交集。该组合已在本仓实测适配并通过验证,包管理器仍会就此报一次 peer 警告。

只有两种被认可的处理方式:接受这一条警告,或加只作用于 Carousel 的窄 override / filter

npm:

{
"overrides": {
"react-native-reanimated-carousel": {
"react-native-gesture-handler": "$react-native-gesture-handler"
}
}
}

$react-native-gesture-handler 会复用消费端根依赖中满足 >=3.0.0 <4.0.0 的版本,避免装第二份 Gesture Handler。

pnpm 用 pnpm.peerDependencyRules.allowedVersions 精确到 react-native-reanimated-carousel>react-native-gesture-handler;Yarn 用 scoped logFilters

禁止全局 peer 忽略、--force--legacy-peer-deps 或无效的 packageExtensions / metadata patch —— 那会连同真实的 major 漂移一起吞掉。

本仓自己的 .yarnrc.yml logFilters 不随 npm 包分发,消费端必须自行选择上述方式之一。本仓的权威门禁是 yarn check:runtime-peers(窄 allowlist:包名 + 请求方 locator + 精确 range + provider major,任一维度漂移即失败),与日志过滤无关。

3. 配 babel(worklets 插件必须最后)

// babel.config.js —— react-native-worklets/plugin 必须排在 plugins 数组最后
module.exports = {
presets: ['module:@react-native/babel-preset'],
plugins: [
// ... 其它插件
'react-native-worklets/plugin',
],
};

根挂 Provider 与 Host

App 根按 GestureHandlerRootView → SafeAreaProvider → ThemeProvider → App 内容 + Hosts 装配。SafeAreaProvider 必须从 react-native-safe-area-context 这个 peer 包导入;设计系统组件与函数仍只从 @unif/react-native-design 包根导入:

import { GestureHandlerRootView } from 'react-native-gesture-handler';
import { SafeAreaProvider } from 'react-native-safe-area-context';
import {
ConfirmHost,
ThemeProvider,
ToastHost,
} from '@unif/react-native-design';

export function App() {
return (
<GestureHandlerRootView style={{ flex: 1 }}>
<SafeAreaProvider>
<ThemeProvider>
{/* 你的导航 / 屏幕 */}
<ToastHost />
<ConfirmHost />
</ThemeProvider>
</SafeAreaProvider>
</GestureHandlerRootView>
);
}
  • ThemeProvider —— 读取 useColorScheme(),自动跟随系统亮暗。
  • ToastHost / ConfirmHost —— 都会读取安全区 context;各挂一个,且必须位于 SafeAreaProvider 内。要在 RN Modal 里显示 toast / confirm 时,可在 Modal 的内容树里再挂一份:后挂载的接管、卸载自动归还(Modal 是独立 native window,根上那份会被它盖住)。
完整 Provider 栈

若宿主还使用键盘或导航 Provider,可在不破坏上述相对顺序的前提下加入,例如 GestureHandlerRootView → KeyboardProvider → SafeAreaProvider → ThemeProvider → NavigationContainer + HostsThemeProvider 接受 forceScheme?: 'light' | 'dark' 强制某主题(用于测试 / 设置项接入)。

第一个主题化组件

颜色 / 阴影走 useThemedStyles(maker),自动跟随亮暗。makeStyles 必须定义在模块顶层 —— 内联进组件会让引用每次渲染都变、打穿缓存。

import { StyleSheet, View, Text } from 'react-native';
import {
Button,
useThemedStyles,
type ColorTokens,
} from '@unif/react-native-design';

// ✅ 模块顶层定义 maker:(colors, shadow) => StyleSheet
const makeStyles = (c: ColorTokens) =>
StyleSheet.create({
wrap: { padding: 16, backgroundColor: c.surface },
title: { color: c.foreground, fontSize: 17, fontWeight: '600' },
});

export function Demo() {
const styles = useThemedStyles(makeStyles);
return (
<View style={styles.wrap}>
<Text style={styles.title}>今日待办</Text>
<Button label="保存" variant="primary" onPress={() => {}} />
</View>
);
}

只需 inline 取一两个颜色(状态映射 / prop fallback)时,用 useColors():

import { useColors } from '@unif/react-native-design';

function Banner({ active }: { active: boolean }) {
const c = useColors(); // 跟随亮暗
return (
<View
style={{ backgroundColor: active ? c.primary : c.surfaceContainer }}
/>
);
}

命令式 API

挂好 host 后,任意位置可直接调用:

import { toast } from '@unif/react-native-design';

toast.success('已保存');

下一步