代码模式与实践Skill code-patterns-practices

本技能是关于React Native移动应用开发的代码模式、最佳实践和常见解决方案的集合。它提供了组件设计、状态管理、数据获取、性能优化、错误处理以及移动端特有问题的实用模式,旨在帮助开发者编写更高质量、更易维护的代码。关键词:React Native, 移动开发, 代码模式, 最佳实践, 性能优化, 组件设计, 状态管理, 自定义Hooks。

移动开发 0 次安装 0 次浏览 更新于 3/2/2026

name: code-patterns-practices description: React Native 编码模式、最佳实践和移动开发的常见解决方案。在实现功能或重构代码时使用。 allowed-tools: Read, Write, Edit

代码模式与实践

React Native 开发的常见模式和最佳实践。

何时使用

  • 实现新功能
  • 重构现有代码
  • 选择架构模式
  • 解决常见问题
  • 提高代码质量

组件模式

自定义 Hooks

// 提取可复用逻辑
function useToggle(initial = false) {
  const [value, setValue] = useState(initial);
  const toggle = useCallback(() => setValue(v => !v), []);
  return [value, toggle] as const;
}

// 用法
const [isOpen, toggleOpen] = useToggle();

复合组件

// 创建灵活的组件 API
interface TabsProps {
  children: React.ReactNode;
  defaultValue?: string;
}

function Tabs({ children, defaultValue }: TabsProps) {
  const [active, setActive] = useState(defaultValue);

  return (
    <TabsContext.Provider value={{ active, setActive }}>
      {children}
    </TabsContext.Provider>
  );
}

Tabs.List = TabsList;
Tabs.Trigger = TabsTrigger;
Tabs.Content = TabsContent;

// 用法
<Tabs defaultValue="home">
  <Tabs.List>
    <Tabs.Trigger value="home">首页</Tabs.Trigger>
    <Tabs.Trigger value="profile">个人资料</Tabs.Trigger>
  </Tabs.List>
  <Tabs.Content value="home">首页内容</Tabs.Content>
  <Tabs.Content value="profile">个人资料内容</Tabs.Content>
</Tabs>

渲染属性

// 共享组件逻辑
interface DataLoaderProps<T> {
  loadData: () => Promise<T>;
  children: (data: T | null, loading: boolean, error: Error | null) => React.ReactNode;
}

function DataLoader<T>({ loadData, children }: DataLoaderProps<T>) {
  const [data, setData] = useState<T | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<Error | null>(null);

  useEffect(() => {
    loadData()
      .then(setData)
      .catch(setError)
      .finally(() => setLoading(false));
  }, [loadData]);

  return <>{children(data, loading, error)}</>;
}

// 用法
<DataLoader loadData={fetchUser}>
  {(user, loading, error) => {
    if (loading) return <Loading />;
    if (error) return <Error error={error} />;
    return <UserProfile user={user} />;
  }}
</DataLoader>

状态管理模式

局部状态

// 尽可能保持简单
function Counter() {
  const [count, setCount] = useState(0);
  return <Button onPress={() => setCount(c => c + 1)}>计数: {count}</Button>;
}

共享状态(Context)

// 用于横切关注点
const ThemeContext = createContext<ThemeContextValue>(null!);

export function ThemeProvider({ children }: { children: React.ReactNode }) {
  const [theme, setTheme] = useState<'light' | 'dark'>('light');

  return (
    <ThemeContext.Provider value={{ theme, setTheme }}>
      {children}
    </ThemeContext.Provider>
  );
}

export function useTheme() {
  const context = useContext(ThemeContext);
  if (!context) throw new Error('useTheme 必须在 ThemeProvider 内使用');
  return context;
}

全局状态(Zustand)

// 用于应用级状态
import { create } from 'zustand';

interface UserState {
  user: User | null;
  setUser: (user: User) => void;
  logout: () => void;
}

export const useUserStore = create<UserState>((set) => ({
  user: null,
  setUser: (user) => set({ user }),
  logout: () => set({ user: null }),
}));

数据获取模式

使用 Async/Await

function useUserData(userId: string) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    let cancelled = false;

    async function fetchData() {
      try {
        const response = await fetch(`/api/users/${userId}`);
        const result = await response.json();
        if (!cancelled) {
          setData(result);
        }
      } catch (err) {
        if (!cancelled) {
          setError(err);
        }
      } finally {
        if (!cancelled) {
          setLoading(false);
        }
      }
    }

    fetchData();

    return () => {
      cancelled = true;
    };
  }, [userId]);

  return { data, loading, error };
}

性能模式

记忆化

// 昂贵计算
const expensiveValue = useMemo(() => {
  return calculateExpensiveValue(data);
}, [data]);

// 稳定的回调函数
const handlePress = useCallback(() => {
  doSomething(value);
}, [value]);

// 组件记忆化
const MemoizedChild = memo(function Child({ data }: ChildProps) {
  return <View>{data}</View>;
});

懒加载

import { lazy, Suspense } from 'react';

const HeavyComponent = lazy(() => import('./HeavyComponent'));

function App() {
  return (
    <Suspense fallback={<Loading />}>
      <HeavyComponent />
    </Suspense>
  );
}

错误处理模式

错误边界

class ErrorBoundary extends React.Component<
  { children: React.ReactNode },
  { hasError: boolean; error: Error | null }
> {
  state = { hasError: false, error: null };

  static getDerivedStateFromError(error: Error) {
    return { hasError: true, error };
  }

  componentDidCatch(error: Error, info: React.ErrorInfo) {
    console.error('捕获的错误:', error, info);
  }

  render() {
    if (this.state.hasError) {
      return <ErrorScreen error={this.state.error} />;
    }
    return this.props.children;
  }
}

Try-Catch 模式

async function saveData() {
  try {
    await api.save(data);
    showSuccess('已保存!');
  } catch (error) {
    if (error instanceof NetworkError) {
      showError('网络错误,请检查连接。');
    } else if (error instanceof ValidationError) {
      showError(error.message);
    } else {
      showError('出错了。');
    }
  }
}

移动端特有模式

安全区域处理

import { useSafeAreaInsets } from 'react-native-safe-area-context';

function Screen() {
  const insets = useSafeAreaInsets();

  return (
    <View style={{ paddingTop: insets.top, paddingBottom: insets.bottom }}>
      {/* 内容 */}
    </View>
  );
}

键盘避让

import { KeyboardAvoidingView, Platform } from 'react-native';

<KeyboardAvoidingView
  behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
  style={{ flex: 1 }}
>
  {/* 输入表单 */}
</KeyboardAvoidingView>

最佳实践

  1. 保持组件小巧:单一职责,易于测试
  2. 提取自定义 Hooks:跨组件复用逻辑
  3. 使用 TypeScript:及早发现错误
  4. 处理加载和错误状态:更好的用户体验
  5. 清理副作用:防止内存泄漏
  6. 明智地优化:优化前先分析性能
  7. 测试行为:关注用户交互

应避免的反模式

  • ❌ 巨型组件(>300 行)
  • ❌ 属性透传(应使用 context/store)
  • ❌ 在 useEffect 中缺少清理
  • ❌ 在 render 中内联函数定义
  • ❌ 直接修改状态
  • ❌ 未经测量的过度优化

资源