mcpField
R
react-core

react-core

github.com/bobmatnyc开发78209 次安装16 周前更新
代码仓库

关于 react-core

面向 React 开发者的基础参考 Skill,也为依赖 React 基础的生态 Skill 提供入门基准。内容涵盖组件、状态、渲染与表单等常见模式。

主要功能

  1. 01组件、JSX、属性与状态
  2. 02核心 Hook 及其用法
  3. 03组合模式与自定义 Hook
  4. 04条件渲染与列表渲染
  5. 05受控表单输入
  6. 06常见误用与规避建议

适用场景

  1. 01构建组件并传递数据
  2. 02为任务选择合适的核心 Hook
  3. 03渲染条件界面和列表
  4. 04实现由状态驱动的表单输入

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/bobmatnyc/claude-mpm-skills --skill react-core

安装后在 Claude Code 中输入/react-core确认已加载。

附带文件metadata.json

详细介绍

React 核心基础

概述

这是 React 通用基础知识的权威参考。本技能涵盖每个 React 应用共有的构建模块:组件和 JSX、属性和状态、核心 Hooks、组合模式、条件渲染和列表渲染,以及受控输入。它是生态系统技能(样式、数据获取、状态管理、部署)的基础“依赖 React”目标,这些技能都默认你了解 React 核心知识。

请将本技能聚焦于基础知识。高级 Hook 组合(由 SWR 支持的自定义 Hook、防抖上下文、记忆化 Provider)请使用同级的 react-hooks-composition 技能。对于复杂 UI 流程的显式有限状态机建模,请使用同级的 react-state-machine 技能。

何时使用本技能

在以下情况下使用本技能:

  • 构建组件、连接属性或管理本地状态
  • 根据具体问题选择合适的核心 Hook
  • 渲染列表或条件 UI
  • 实现受控表单输入
  • 为依赖 React 生态系统技能建立基础

组件和 JSX

React 组件是一个返回 JSX 的函数。组件名称使用 PascalCase。返回单个根节点,或使用片段(<>...</>)包裹多个同级元素。

type GreetingProps = {
  name: string;
};

function Greeting({ name }: GreetingProps) {
  return (
    <>
      <h1>Hello, {name}</h1>
      <p>Welcome back.</p>
    </>
  );
}

JSX 使用 {} 嵌入表达式。属性使用驼峰命名法(className、onClick、htmlFor)。JSX 返回 UI 描述;React 会将其与 DOM 协调。

属性和状态

属性将数据从父组件传递给子组件,在子组件中只读。状态保存组件自身拥有并会随时间变化的数据。

import { useState } from 'react';

function Counter({ step = 1 }: { step?: number }) {
  const [count, setCount] = useState(0);

  return (
    <button onClick={() => setCount((prev) => prev + step)}>
      Count: {count}
    </button>
  );
}

将属性和状态视为不可变数据。通过 setter 更新状态;当下一个值取决于前一个值时,优先使用函数式更新器(setCount(prev => prev + 1))。

核心 Hooks 概览

只能在组件或自定义 Hook 的顶层调用 Hook,不能在条件语句、循环或嵌套函数中调用。此规则可确保每次渲染时 Hook 的调用顺序保持稳定。

useState — 组件本地状态

保存一个值及其 setter。值发生变化时会重新渲染组件。

const [open, setOpen] = useState(false);
useEffect — 与外部系统同步

在渲染后运行以执行副作用:订阅、计时器、数据获取、手动 DOM 操作。依赖数组控制 Effect 何时重新运行。返回清理函数以清除订阅。

import { useEffect, useState } from 'react';

function WindowWidth() {
  const [width, setWidth] = useState(window.innerWidth);

  useEffect(() => {
    const onResize = () => setWidth(window.innerWidth);
    window.addEventListener('resize', onResize);
    return () => window.removeEventListener('resize', onResize);
  }, []); // empty deps: subscribe once on mount, clean up on unmount

  return <span>{width}px</span>;
}
useRef — 在渲染间保持的可变值

保存可变值,但不会触发重新渲染。常见用途:引用 DOM 节点,或在渲染间保存值(计时器 ID、之前的值)。

import { useRef, useEffect } from 'react';

function AutoFocusInput() {
  const inputRef = useRef<HTMLInputElement>(null);
  useEffect(() => inputRef.current?.focus(), []);
  return <input ref={inputRef} />;
}
useMemo — 缓存开销较大的计算

仅当依赖项变化时才重新计算值。仅在计算确实开销较大,或需要稳定传递给记忆化子组件的引用标识时使用。

const sorted = useMemo(() => items.slice().sort(compare), [items]);
useCallback — 稳定函数引用

只要依赖项相等,每次渲染都会返回同一个函数实例。将稳定的回调传递给记忆化子组件,或放入 Effect 依赖数组。

const handleSelect = useCallback((id: string) => onSelect(id), [onSelect]);
useContext — 无需逐层传递属性即可读取共享状态

读取组件树上层提供的上下文当前值。

import { createContext, useContext } from 'react';

const ThemeContext = createContext<'light' | 'dark'>('light');

function ThemedLabel() {
  const theme = useContext(ThemeContext);
  return <span className={theme}>Themed</span>;
}

关于可避免消费者不必要重新渲染的记忆化 Provider 模式,请参阅 react-hooks-composition。

组合模式

优先采用组合,而非配置。通过 children 传递内容,通过属性传递行为。

function Card({ title, children }: { title: string; children: React.ReactNode }) {
  return (
    <section className="card">
      <h2>{title}</h2>
      <div className="card-body">{children}</div>
    </section>
  );
}

// Usage
<Card title="Profile">
  <Avatar />
  <p>Bio text</p>
</Card>;

将共享逻辑提取到自定义 Hook(useSomething)中,而不是在组件间复制。保持组件小巧且职责单一。

条件渲染和列表渲染

使用 && 按条件渲染内容,或使用三元表达式在两种结果间选择。使用 map 渲染列表,并为每个项目提供基于其身份而非数组索引(顺序可能变化时)的稳定 key。

function TodoList({ todos }: { todos: { id: string; text: string; done: boolean }[] }) {
  if (todos.length === 0) return <p>No todos yet.</p>;

  return (
    <ul>
      {todos.map((todo) => (
        <li key={todo.id}>
          {todo.done ? <s>{todo.text}</s> : todo.text}
        </li>
      ))}
    </ul>
  );
}

受控输入

受控输入的值来自状态,并通过 onChange 报告变化。状态是唯一可信来源。

import { useState } from 'react';

function NameField() {
  const [name, setName] = useState('');

  return (
    <label>
      Name
      <input
        value={name}
        onChange={(event) => setName(event.target.value)}
      />
    </label>
  );
}

应避免的反模式

❌ 不要:直接修改状态

直接修改会跳过 setter,因此 React 不会重新渲染。

// BAD: mutates the array in place; React sees the same reference
function addItem(items: string[], next: string) {
  items.push(next);
  setItems(items);
}
// GOOD: create a new array so the reference changes
function addItem(items: string[], next: string) {
  setItems([...items, next]);
}
❌ 不要:有条件地调用 Hooks

有条件地调用 Hook 会破坏 React 所依赖的稳定调用顺序。

// BAD: hook call order changes between renders
function Profile({ id }: { id?: string }) {
  if (id) {
    const data = useUser(id); // conditional hook call
    return <span>{data.name}</span>;
  }
  return null;
}
// GOOD: call the hook unconditionally; branch on its result
function Profile({ id }: { id?: string }) {
  const data = useUser(id); // useUser must accept an undefined id (no fetch / returns null) so the hook is always called
  if (!id || !data) return null;
  return <span>{data.name}</span>;
}
❌ 不要:将数组索引用作可重排列表的 key

当项目移动时,索引 key 会导致 React 错误地归属状态。

// BAD: index key breaks on reorder/insert/delete
{items.map((item, i) => <Row key={i} item={item} />)}
// GOOD: stable identity key
{items.map((item) => <Row key={item.id} item={item} />)}

何时使用相邻技能

  • react-hooks-composition:高级自定义 Hook 组合——基于 SWR 的数据获取、具有双重加载状态的防抖搜索、记忆化上下文提供程序,以及可复用的异步状态 Hook。
  • react-state-machine:使用 XState v5 显式建模有限状态机,适用于复杂流程(多步骤表单、媒体播放器、带动画的模态框),确保不可能出现的状态无法表示。
  • react-advanced:React 19 平台功能与渲染架构——React Compiler(自动记忆化)、并发渲染、use() Hook、Actions、虚拟化、代码拆分和 RSC 边界。

最佳实践总结

  1. 组件返回 JSX:使用 PascalCase 名称,并返回单个根元素或片段。
  2. Props 只读:向下传递数据;共享状态时,将状态提升到共同位置。
  3. 以不可变方式更新状态:使用 setter,优先采用函数式更新器。
  4. 只在顶层调用 Hook:绝不要有条件地调用 Hook。
  5. 副作用用于同步外部系统:通过依赖项限定作用范围,并清理订阅。
  6. 有意进行记忆化:对开销较大的操作或需要稳定标识的值使用 useMemo/useCallback,而非默认使用。
  7. 稳定的 key:根据标识而非数组索引为列表项设置 key。
  8. 受控输入:状态是唯一真实来源。

参考资料

评论

支持 Markdown