Loading...
Loading...
Compare original and translation side by side
interfaceReact.FCinterface ButtonProps {
label: string;
onClick: () => void;
disabled?: boolean;
}
export function Button({ label, onClick, disabled }: ButtonProps) {
return <button onClick={onClick} disabled={disabled}>{label}</button>;
}React.MouseEvent<HTMLButtonElement>React.ChangeEvent<HTMLInputElement>React.ReactNodeinterfaceReact.FCinterface ButtonProps {
label: string;
onClick: () => void;
disabled?: boolean;
}
export function Button({ label, onClick, disabled }: ButtonProps) {
return <button onClick={onClick} disabled={disabled}>{label}</button>;
}React.MouseEvent<HTMLButtonElement>React.ChangeEvent<HTMLInputElement>React.ReactNodeconst [count, setCount] = useState(0);
// Always use functional updates when new state depends on old
setCount(prev => prev + 1); // Good
setCount(count + 1); // Avoid - can be stale in closuresconst [count, setCount] = useState(0);
// 当新状态依赖旧状态时,始终使用函数式更新
setCount(prev => prev + 1); // 推荐写法
setCount(count + 1); // 避免使用——闭包中可能出现状态过期问题useEffect(() => {
const controller = new AbortController();
fetch('/api/data', { signal: controller.signal })
.then(res => res.json())
.then(data => setData(data));
return () => controller.abort(); // Cleanup
}, []);useEffect(() => {
const controller = new AbortController();
fetch('/api/data', { signal: controller.signal })
.then(res => res.json())
.then(data => setData(data));
return () => controller.abort(); // 清理操作
}, []);children: React.ReactNode<Select><Select.Option /></Select>children: React.ReactNode<Select><Select.Option /></Select>useMemouseCallbackReact.memouseMemouseCallbackReact.memo| Excuse | Reality |
|---|---|
| "useEffect is fine for derived state" | Calculate derived values directly. useEffect for derived state causes extra renders and bugs. |
| "React.FC is the standard way" | Community moved away from React.FC. Use explicit function declarations with typed props. |
| "Cleanup doesn't matter for short operations" | Memory leaks are real. Always cleanup subscriptions, timers, and abort fetch requests. |
| "Missing dependencies is fine, I know what I'm doing" | Stale closures cause bugs. Always include all dependencies. Fix the root cause, don't lie to the linter. |
| "useCallback with all dependencies is correct" | Including state in deps creates new function every render AND stale closures. Use functional setState updates instead. |
| "This is Functional Core because it's pure logic" | Hooks with state are Imperative Shell or Mixed. Only pure functions without hooks are Functional Core. |
| "Array index as key is fine for static lists" | If list ever reorders, filters, or updates, you'll get bugs. Use stable unique IDs. |
| "Mutating state is faster" | React won't detect the change. Always create new objects/arrays. |
| 借口 | 实际情况 |
|---|---|
| "useEffect用于派生状态没问题" | 直接计算派生值即可。用useEffect处理派生状态会导致额外渲染和bug。 |
| "React.FC是标准写法" | 社区已逐渐摒弃React.FC。使用带类型props的显式函数声明。 |
| "短时间操作不需要清理" | 内存泄漏是真实存在的问题。始终清理订阅、定时器,并终止fetch请求。 |
| "遗漏依赖项没关系,我知道自己在做什么" | 过期闭包会引发bug。始终包含所有依赖项。修复根本问题,不要欺骗linter。 |
| "包含所有依赖项的useCallback是正确的" | 依赖项中包含状态会导致每次渲染创建新函数,同时引发过期闭包问题。改用函数式setState更新。 |
| "这是函数式核心,因为它是纯逻辑" | 带状态的hooks属于命令式外壳或混合模式。只有不含hooks的纯函数才是函数式核心。 |
| "静态列表用数组索引作为key没问题" | 一旦列表重新排序、过滤或更新,就会出现bug。使用稳定的唯一ID。 |
| "直接修改状态速度更快" | React无法检测到此类变更。始终创建新的对象/数组。 |
| Task | Pattern |
|---|---|
| Props | |
| State update | |
| Fetch on mount | |
| Derived value | Calculate directly, NOT useEffect |
| List render | |
| 任务 | 模式 |
|---|---|
| Props定义 | |
| 状态更新 | 当依赖当前状态时,使用 |
| 挂载时请求数据 | |
| 派生值 | 直接计算,不使用useEffect |
| 列表渲染 | |
React.FCuseEffectkey={index}state.value = xanyReact.FCkey={index}state.value = xany