首页 / 速查手册 / 在线

React速查手册

React组件/Hooks/状态管理速查表

速查手册 · 1 次 · 2026-10-04 · 分享 · 全屏

⚛️ 函数组件与 JSX

第一个函数组件

组件名必须大写,返回 JSX;18 版无需手动 import React。

// Hello.jsx
export default function Hello() {
  const name = 'React';
  return (
    <div className="hello">
      <h1>Hello, {name}!</h1>
      <p>{1 + 2}</p>
    </div>
  );
}

// 使用
import Hello from './Hello';
<Hello />
JSX 属性与样式

class 写成 className,for 写成 htmlFor,style 接收对象。

<img src="/a.png" alt="图" />
<a href="/x" title="提示">链接</a>
<label htmlFor="name">姓名</label>
<input id="name" maxLength={10} disabled={false} />

<div style={{color: 'red', fontSize: 16, marginTop: 8}}>
  样式名用驼峰
</div>

<div className={['card', active && 'active'].filter(Boolean).join(' ')} />
JSX 注释与表达式

注释要放在花括号里;JSX 只能有一个根节点。

<div>
  {/* 这是 JSX 注释 */}
  <p>{user.name || '游客'}</p>
  <p>{age >= 18 ? '成年' : '未成年'}</p>
  {null}
  {false}
  {undefined}
</div>
Fragment 片段

不想要多余包裹层 div 时使用,短写法 <>...</> 不能加 key。

import {Fragment} from 'react';

function Columns() {
  return (
    <>
      <td>姓名</td>
      <td>年龄</td>
    </>
  );
}

// 需要 key 时必须用完整写法
list.map(it => (
  <Fragment key={it.id}>...</Fragment>
));

📨 props

传递 props

父组件以属性形式传入,子组件通过参数接收(可直接解构)。

// 子组件
function Welcome({name, age}) {
  return <p>{name},{age} 岁</p>;
}

// 父组件
<Welcome name="Tom" age={18} />

// 透传一组属性
const props = {name: 'Amy', age: 20};
<Welcome {...props} />
children 与默认值

children 是标签之间的内容;默认参数给兜底值。

function Card({title = '提示', children}) {
  return (
    <section className="card">
      <h3>{title}</h3>
      <div>{children}</div>
    </section>
  );
}

<Card title="用户协议">
  <p>这里是任意内容</p>
</Card>
子传父:回调 props

父组件把函数传给子组件,子组件在事件中调用并携带数据。

function Child({onSelect}) {
  return <button onClick={() => onSelect('A')}>选 A</button>;
}

function Parent() {
  const [choice, setChoice] = useState('');
  return (
    <>
      <p>已选:{choice}</p>
      <Child onSelect={v => setChoice(v)} />
    </>
  );
}

🎣 useState 状态

基本用法

返回 [值, 更新函数];调用更新函数触发重新渲染。

import {useState} from 'react';

function Counter() {
  const [count, setCount] = useState(0);
  return (
    <button onClick={() => setCount(count + 1)}>
      点击 {count} 次
    </button>
  );
}

const [name, setName] = useState('Tom');   // 字符串
const [list, setList] = useState([]);      // 数组
const [user, setUser] = useState(null);    // 对象/null
函数式更新

新值依赖旧值时,传更新函数,避免闭包读到旧值。

setCount(c => c + 1);
setCount(c => c + 1);   // 连续调用也正确累加

// 初始值需要昂贵计算时,传惰性初始化函数,只执行一次
const [rows, setRows] = useState(() => {
  return JSON.parse(localStorage.getItem('rows') || '[]');
});
更新对象 / 数组(不可变)

状态必须整体替换,不能直接修改原对象,用展开运算符合并。

const [form, setForm] = useState({name: '', age: 0});
setForm(f => ({...f, age: f.age + 1}));

const [list, setList] = useState([1, 2]);
setList(l => [...l, 3]);                     // 追加
setList(l => l.filter(x => x !== 2));        // 删除
setList(l => l.map(x => x === 1 ? 10 : x));  // 修改
setList(l => [0, ...l]);                     // 前插

🔄 useEffect 副作用

挂载后请求数据

空依赖数组只在挂载后执行一次;内部用 async IIFE。

function User({id}) {
  const [user, setUser] = useState(null);

  useEffect(() => {
    let cancelled = false;
    (async () => {
      const res = await fetch(`/api/users/${id}`);
      const data = await res.json();
      if (!cancelled) setUser(data);
    })();
    return () => { cancelled = true; };
  }, [id]);

  return <p>{user?.name ?? '加载中...'}</p>;
}
依赖数组的三种写法

无数组每次渲染执行;[] 仅一次;[dep] 依赖变化才执行。

useEffect(() => {
  document.title = `计数 ${count}`;
}, [count]);          // count 变化时重新执行

useEffect(() => {
  initChart();
}, []);               // 仅挂载后一次

useEffect(() => {
  doSomething();      // 不写数组:每次渲染后都执行(少用)
});
清理函数

return 的函数在卸载或下次执行前调用,用于清除订阅/定时器。

useEffect(() => {
  const t = setInterval(() => console.log('tick'), 1000);
  window.addEventListener('resize', onResize);

  return () => {
    clearInterval(t);
    window.removeEventListener('resize', onResize);
  };
}, []);

useEffect(() => {
  const ws = new WebSocket('/ws');
  return () => ws.close();
}, []);

🖱 事件处理

事件对象

合成事件 SyntheticEvent,API 与原生基本一致。

function Form() {
  return (
    <form onSubmit={e => {
      e.preventDefault();
      console.log('提交但不刷新页面');
    }}>
      <button type="submit">提交</button>
    </form>
  );
}

<button onClick={e => {
  e.stopPropagation();
  console.log(e.type, e.currentTarget.tagName);
}}>点我</button>
向事件处理函数传参

箭头函数包一层即可拿到自定义参数与事件对象。

{users.map(u => (
  <button
    key={u.id}
    onClick={e => handleDelete(u.id, e)}
  >
    删除 {u.name}
  </button>
))}

// 柯里化写法
const handleDelete = id => e => {
  console.log(id, e);
};
<button onClick={handleDelete(u.id)}>删除</button>

📋 列表与条件渲染

列表渲染与 key

map 返回元素数组;每个元素必须有稳定且唯一的 key。

<ul>
  {todos.map(todo => (
    <li key={todo.id} className={todo.done ? 'done' : ''}>
      {todo.title}
    </li>
  ))}
</ul>

{items.map((item, i) => (
  <tr key={item.id}>...</tr>   // 万不得已才用 index 作 key
))}
条件渲染

&& 短路适合“要么显示要么不显示”;三元适合二选一。

{isLoggedIn && <LogoutButton />}

{loading ? (
  <Spinner />
) : (
  <Content />
)}

{role === 'admin' && <AdminPanel />}
{count > 0 && <Badge count={count} />}

{status === 'error' && <p className="err">出错了</p>}
key 的注意事项

key 要用稳定 id;列表会排序、插入、删除时用 index 会造成状态错位。

// ❌ 不好:index 作 key,删除中间项会导致输入框内容错位
{list.map((item, index) => <InputRow key={index} />)}

// ✅ 好:业务主键
{list.map(item => <InputRow key={item.uuid} />)}

// key 在兄弟之间唯一即可,无需全局唯一
// 不要用 Math.random() 当 key,每次渲染都变等于全部重建

📝 受控表单

受控输入框

value 绑定状态、onChange 更新状态,React 成为“单一数据源”。

function SearchBox() {
  const [kw, setKw] = useState('');
  return (
    <>
      <input
        value={kw}
        onChange={e => setKw(e.target.value)}
        placeholder="搜索..."
      />
      <p>你输入了:{kw}</p>
    </>
  );
}
多字段统一处理

给每个 input 加 name,用一个 onChange 处理整个表单。

const [form, setForm] = useState({name: '', email: '', age: ''});

const handleChange = e => {
  const {name, value} = e.target;
  setForm(f => ({...f, [name]: value}));
};

<input name="name" value={form.name} onChange={handleChange} />
<input name="email" value={form.email} onChange={handleChange} />
<button onClick={() => console.log(form)}>提交</button>
checkbox / radio / select

勾选类控件读写 checked;select 也是受控 value。

const [agree, setAgree] = useState(false);
<input
  type="checkbox"
  checked={agree}
  onChange={e => setAgree(e.target.checked)}
/>

<select value={city} onChange={e => setCity(e.target.value)}>
  <option value="bj">北京</option>
  <option value="sh">上海</option>
</select>

<input type="radio" name="sex" value="M"
  checked={sex === 'M'} onChange={setSex} />

⚡ useMemo / useCallback / useRef

useMemo 缓存计算结果

昂贵计算依赖未变时复用结果;不要滥用,先做性能测量。

const total = useMemo(
  () => items.reduce((s, it) => s + it.price * it.qty, 0),
  [items]
);

const filtered = useMemo(
  () => list.filter(u => u.name.includes(kw)),
  [list, kw]
);
useCallback 缓存函数

保持函数引用稳定,常配合 memo 子组件或 effect 依赖使用。

const fetchUser = useCallback(async (id) => {
  const res = await fetch(`/api/users/${id}`);
  return res.json();
}, []);

useEffect(() => {
  fetchUser(id).then(setUser);
}, [id, fetchUser]);

const MemoChild = memo(Child);   // props 引用不变则跳过渲染
useRef 引用 DOM 与保存可变值

ref.current 变化不触发重渲染;常用于 DOM、定时器句柄。

function AutoFocus() {
  const inputRef = useRef(null);
  useEffect(() => {
    inputRef.current.focus();
  }, []);
  return <input ref={inputRef} />;
}

const timerRef = useRef(null);
useEffect(() => {
  timerRef.current = setInterval(tick, 1000);
  return () => clearInterval(timerRef.current);
}, []);

🧱 组件复用

自定义 Hook

以 use 开头的函数,内部可组合其他 Hook,实现逻辑复用。

function useToggle(initial = false) {
  const [on, setOn] = useState(initial);
  const toggle = useCallback(() => setOn(v => !v), []);
  return [on, toggle];
}

function Panel() {
  const [open, toggleOpen] = useToggle(true);
  return <button onClick={toggleOpen}>{open ? '收起' : '展开'}</button>;
}
useContext 跨层传值

避免 props 逐层透传;上层 Provider 提供值。

const ThemeContext = createContext('light');

function App() {
  return (
    <ThemeContext.Provider value="dark">
      <Page />
    </ThemeContext.Provider>
  );
}

function Button() {
  const theme = useContext(ThemeContext);
  return <button className={theme}>按钮</button>;
}
请求三态 loading/error/data

组织异步数据的标准模式,配合自定义 Hook 复用。

function useFetch(url) {
  const [data, setData] = useState(null);
  const [error, setError] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    let ok = true;
    setLoading(true);
    fetch(url)
      .then(r => r.json())
      .then(d => ok && setData(d))
      .catch(e => ok && setError(e))
      .finally(() => ok && setLoading(false));
    return () => { ok = false; };
  }, [url]);

  return {data, error, loading};
}

📖 使用说明

全程在浏览器本地运行。

操作步骤:

  1. 搜索或浏览分类条目;
  2. 查看语法与示例代码;
  3. 点击复制代码块。

💬 用户评论 (0)

还没有评论,快来抢沙发!

请添加微信联系我