React速查手册
React组件/Hooks/状态管理速查表
⚛️ 函数组件与 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 />
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 只能有一个根节点。
<div>
{/* 这是 JSX 注释 */}
<p>{user.name || '游客'}</p>
<p>{age >= 18 ? '成年' : '未成年'}</p>
{null}
{false}
{undefined}
</div>
不想要多余包裹层 div 时使用,短写法 <>...</> 不能加 key。
import {Fragment} from 'react';
function Columns() {
return (
<>
<td>姓名</td>
<td>年龄</td>
</>
);
}
// 需要 key 时必须用完整写法
list.map(it => (
<Fragment key={it.id}>...</Fragment>
));
📨 props
父组件以属性形式传入,子组件通过参数接收(可直接解构)。
// 子组件
function Welcome({name, age}) {
return <p>{name},{age} 岁</p>;
}
// 父组件
<Welcome name="Tom" age={18} />
// 透传一组属性
const props = {name: 'Amy', age: 20};
<Welcome {...props} />
children 是标签之间的内容;默认参数给兜底值。
function Card({title = '提示', children}) {
return (
<section className="card">
<h3>{title}</h3>
<div>{children}</div>
</section>
);
}
<Card title="用户协议">
<p>这里是任意内容</p>
</Card>
父组件把函数传给子组件,子组件在事件中调用并携带数据。
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>
📋 列表与条件渲染
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 要用稳定 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>
勾选类控件读写 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
昂贵计算依赖未变时复用结果;不要滥用,先做性能测量。
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]
);
保持函数引用稳定,常配合 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 引用不变则跳过渲染
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);
}, []);
🧱 组件复用
以 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>;
}
避免 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>;
}
组织异步数据的标准模式,配合自定义 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};
}
😶 没有匹配的条目,换个关键词试试
📖 使用说明
全程在浏览器本地运行。
操作步骤:
- 搜索或浏览分类条目;
- 查看语法与示例代码;
- 点击复制代码块。
💬 用户评论 (0)
还没有评论,快来抢沙发!