升级 / 迁移
破坏性变更与迁移方法。当前版本的完整 token 见设计令牌,组件 API 见组件概览。
令牌迁移:旧顶层导出 → 运行期 Hook
背景
旧版 @unif/react-native-design 从顶层直接导出 colors 和 shadow 对象,可在模块顶层静态 import。这种写法只有单一亮色值,无法随系统亮暗切换 —— 顶层静态导出已删除:
// ❌ Incorrect:顶层 colors / shadow 导出已删除,拿不到;且只有亮色值
import { colors, shadow } from '@unif/react-native-design';
const styles = StyleSheet.create({
container: {
backgroundColor: colors.surface, // 静态,不随亮 / 暗切换
...shadow.brandLg,
},
});
迁移方式
颜色 + 阴影:改用运行期 hook。useThemedStyles(maker) 的 maker 签名是 (c: ColorTokens, s: ShadowTokens) => StyleSheet,在组件内调用即拿到当前主题的 styles。
// ✅ Correct:运行期 hook,自动随主题切换
import { useThemedStyles } from '@unif/react-native-design';
import type { ColorTokens, ShadowTokens } from '@unif/react-native-design';
import { StyleSheet } from 'react-native';
// makeStyles 必须在模块顶层定义(不能内联进组件,否则打穿 useMemo 缓存)
const makeStyles = (c: ColorTokens, s: ShadowTokens) =>
StyleSheet.create({
container: {
backgroundColor: c.surface,
...s.brandLg, // 暗色下 shadowOpacity / elevation 自动趋零
},
});
function MyComponent() {
const styles = useThemedStyles(makeStyles);
// ...
}
只需 inline 取色时用 useColors()(返回 ColorTokens),取阴影用 useShadow()(返回 ShadowTokens)。
间距 / 圆角 / 字体 / 动效:这些是静态 token,继续直接 import:
import {
space,
radius,
type as t,
fw,
fontMono,
motion,
} from '@unif/react-native-design';
对照速查
| 旧写法(已删除) | 新写法(正确) |
|---|---|
import { colors } from '@unif/react-native-design' | const c = useColors() |
import { shadow } from '@unif/react-native-design' | const s = useShadow(),或 maker 第二参 (c, s) => ... |
colors.primary / colors.surface / colors.foreground | c.primary / c.surface / c.foreground |
shadow.brandLg | ...s.brandLg(spread 进 StyleSheet) |
顶层 StyleSheet.create({ ... colors.x ... }) | useThemedStyles(maker) 运行期 |
旧 token 名 → 新 role 名
历史代码里若残留旧的强度档命名,grep 替换为 role 名:
| 旧 | 新 |
|---|---|
colors.bgPage | c.background |
colors.bgCard | c.surface |
colors.bgInput | c.surfaceContainer |
colors.bgMuted | c.surfaceContainerHigh |
colors.bgPill | c.surfaceContainerHighest |
colors.fg1 / fg2 / fg3 | c.foreground / c.foregroundMuted / c.foregroundSubtle |
colors.primary300 / 500 | c.primary / c.primaryPressed |
colors.primary0 / 50 | c.primaryContainer / c.primaryContainerSubtle |
colors.success300 / successBg | c.success / c.successContainer |
colors.error300 / error0 | c.error / c.errorContainer |
colors.info300 / infoBg | c.info / c.infoContainer |
colors.border / borderSoft / borderFaint | c.outline / c.outlineVariant / c.outlineFaint |
旧
brandGradient/primary100/200/400/600等强度档已随死代码清理移除(0 消费方)。迁移对照见本页的令牌迁移表。
为什么不能继续用静态导出
ThemeProvider 读 useColorScheme() 动态算亮 / 暗,并以 [scheme, fontScale] 为 useMemo 依赖,把稳定的 colors / shadow 引用和字号倍数注入 Context。useThemedStyles(maker) 的 useMemo([colors, shadow, fontScale, maker]) 依赖这些值 —— 静态顶层导出永远只有亮色值,亮暗切换和应用级字号档位都对它无效。
版本升级注意事项
0.6.0 移除 BottomSheet;当前 Confirm 已重新提供
0.6.0 曾同时移除 BottomSheet 与旧 Confirm 实现,并去掉
@gorhom/bottom-sheet 依赖。当前版本仍不提供 BottomSheet,但已经重新公开
confirm()、<ConfirmHost /> 与 ConfirmOptions;新的 Confirm 使用裸 RN
Modal + 栈式 owner Store,不依赖 @gorhom。
// ❌ BottomSheet 当前仍未从包根导出
import { BottomSheet } from '@unif/react-native-design';
// ✅ 当前命令式确认 API
import { ConfirmHost, confirm } from '@unif/react-native-design';
// App 根附近挂一个
function AppOverlays() {
return <ConfirmHost />;
}
async function requestDelete() {
const accepted = await confirm({
title: '确认删除?',
destructive: true,
});
// 根据 accepted 决定是否继续
}
迁移建议:
- 底部 sheet / 弹层 → 用 React Navigation 的
presentation: 'formSheet'(原生 sheet,系统接管手势 / 动画 / 变暗),或自持 sheet 容器。 - 命令式确认 → 使用包根导出的
confirm(),并在SafeAreaProvider内挂一个<ConfirmHost />。生命周期、重入和无 Host 语义见 Confirm。
同时 Toast 新增 position('top' | 'bottom' | 'center',默认 'bottom'),详见 Toast。
升级 react-native-reanimated 4.x
Reanimated 4 使用新的 worklet 插件 react-native-worklets/plugin 替代旧的 react-native-reanimated/plugin。babel.config.js 里 worklets 插件必须排在 plugins 数组最后:
// babel.config.js
module.exports = {
plugins: [
// ... 其它插件
// worklets 插件必须最后
'react-native-worklets/plugin',
],
};