关注【索引目录】服务号,更多精彩内容等你来探索!
React 新手?
如果是的话,您可能想知道您真正需要什么钩子 - 或者更糟糕的是,您在没有意识到的情况下一遍又一遍地复制相同的逻辑。
这篇文章涵盖了您在项目中可能需要的所有 React hooks。
让我们深入了解一下 。
1. useState
这个钩子是不可避免的。
每当您需要在重新渲染后仍保持动态状态时,这就是您要找的。
const [count, setCount] = useState(0);
2. useReducer
一旦你的状态变得复杂(例如多个相关字段),useReducer它就会成为你的朋友。
它还可以与 完美搭配useContext,让您可以通过简单的dispatch调用来更新状态。
const reducer = (state, action) => {
switch (action.type) {
case "addTodo":
return { todos: [...state.todos, action.todo] };
case "removeTodo":
// TODO: Implement logic
case "toggleTodo":
// TODO: Implement logic
default:
return state;
}
};
const [state, dispatch] = useReducer(reducer, { todos: [] });
3. useContext
当螺旋桨钻孔失控时,这个钩子可以挽救局面。
Prop 钻取= 将 props 穿过多层只是为了到达深层嵌套的组件。
用于useContext:
-
在小型应用程序中管理全局状态 -
像经过身份验证的用户一样共享数据 -
避免到处手动传递 props
const UserContext = createContext();
function App() {
const user = useUser();
return (
<UserContext.Provider value={user}>
{/* ... */}
</UserContext.Provider>
);
}
function Profile() {
const user = useContext(UserContext);
return <div>Hello {user.name}</div>;
}
4. useEffect
99% 的情况下,你应该避免它。
(参见:你可能不需要它)
但在现实生活中,您仍然需要它 - 尤其是对于与外部系统同步之类的事情。
function useSetDocumentTitle(title: string) {
useEffect(() => {
document.title = title;
}, [title]);
}
5. useRef
您永远不应该在 React 中直接操作 DOM。
但是当你必须这样做的时候(例如对于画布、图表库……),useRef这是安全的方法。
function ExampleChart({ data }) {
const canvasRef = useRef();
useEffect(() => {
const ctx = canvasRef.current;
if (!ctx) return;
const chart = new Chart(ctx, {
type: "bar",
data: {
labels: data.map((row) => row.year),
datasets: [{ label: "Likes", data: data.map((r) => r.count) }],
},
});
return () => chart.destroy();
}, []);
return <canvas ref={canvasRef} />;
}
6. useMemo / useCallback
由于新的 React Compiler,这些可能会变得可选项 - 但就目前而言,它们仍然有用。
使用useMemo情况:
-
昂贵的计算不应该在每次渲染时重新运行 -
你正在记忆一个非原始依赖项 -
您正在向 memo包装的组件传递值
用于useCallback记忆函数。
const total = useMemo(() => computeTotal(items), [items]);
const handleClick = useCallback(() => {
console.log("clicked");
}, []);
7. 使用布局效果
这个虽然罕见,但很有用。
它在绘制之前运行,这有助于防止布局偏移或闪烁的 UI。
请参阅此处的真实示例:不再闪烁的用户界面
如果您对 React 组件生命周期不熟悉,请查看我的帖子✨3 分钟内了解 React 生命周期 。
useLayoutEffect(() => {
const height = ref.current.offsetHeight;
setHeight(height);
}, []);
8. useSWR/useQuery
SWR和TanStack Query正在成为 React 中获取数据的标准。
SWR 更简单,适用于大多数用例,而 TanStack Query 更复杂,功能更强大。
驻波比
const fetcher = (url) => fetch(url).then((res) => res.json());
const { data, error, isLoading } = useSWR("/api/user", fetcher);
TanStack 查询
const getUser = () => fetch("/api/user").then((res) => res.json());
const { data, isLoading } = useQuery({
queryKey: ["user"],
queryFn: getUser,
});
9. useSelector、useDispatch 或其他状态钩子
有时 React 的内置状态工具还不够用。
然后您将看到这些取决于状态库的钩子:
useSelector, useDispatch来自react-reduxuseAtom来自Jotai -
ETC。
10. 使用导航
React Router非常流行。
它的导航钩子也是如此:
const navigate = useNavigate();
navigate("/profile");
现在,让我们来讨论一下我在几乎每个应用程序中都会用到的钩子——尽管它们不是 React 内置的。
11. useBoolean
我一直以来最喜欢的之一。
它使管理布尔状态变得非常干净。
const { value: isOpen, setFalse, toggle } = useBoolean();
return (
<>
<button onClick={toggle}>
{isOpen ? "Close form" : "Open form"}
</button>
<Dialog isOpen={isOpen} onClose={setFalse}>
{/* Form content */}
</Dialog>
</>
);
12. 使用CopyToClipboard
非常适合“复制”按钮。
const [copiedText, copy] = useCopyToClipboard();
const handleCopy = () => {
copy("Hello World").catch(err => {
errorToast("Failed to copy!", err);
});
};
return (
<>
<button onClick={handleCopy}>Copy</button>
{copiedText && <span>Copied!</span>}
</>
);
13. usePrevious
使用它来比较当前值与以前的值。
非常适合根据变化触发动作。
const prevCount = usePrevious(count);
const didIncrease = prevCount !== undefined && count > prevCount;
useEffect(() => {
if (didIncrease) {
console.log("Count increased!");
}
}, [didIncrease]);
14. 使用Debounce
消除请求抖动以避免不必要的 API 调用。
const [query, setQuery] = useState("");
const [debouncedQuery] = useDebounce(query, 500);
const { data } = useSWR(`/api/search?q=${debouncedQuery}`, fetcher);
return (
<>
<input
value={query}
onChange={(e) => setQuery(e.target.value)}
placeholder="Search..."
/>
{/* TODO: Show data */}
</>
);
15. useMediaQuery
想要根据屏幕尺寸渲染不同的内容吗?这个钩子很适合你。
const isMobile = useMediaQuery("(max-width: 768px)");
return <div>{isMobile ? "Mobile View" : "Desktop View"}</div>;
16. useResizeObserver
对于响应式布局或像react-window这样的库很有用。
const ref = useRef(null);
const { width = 0, height = 0 } = useResizeObserver({ ref });
return (
<div ref={ref}>
Width: {width}, Height: {height}
</div>
);
17. 使用本地存储
轻松存储和同步数据localStorage。
const [theme, setTheme] = useLocalStorage("theme", "light");
return (
<button onClick={() => setTheme(theme === "light" ? "dark" : "light")}>
Switch to {theme === "light" ? "dark" : "light"}
</button>
);
概括
就是这样!
这 17 个钩子足以覆盖任何 React 应用程序中的大多数用例。
选择您最喜欢的并在下一个项目中使用它们。
关注【索引目录】服务号,更多精彩内容等你来探索!

