一、useRef
1. 基础概念:
useRef 返回一个可变的 ref 对象,这个对象的 .current 属性可以用来存储一个值,该值在组件的生命周期内是持久化的,并且它不会导致组件重新渲染。
语法:
const myRef = useRef(initialValue);
initialValue:这是useRef的初始值,通常是null或者某个值。myRef:这是返回的一个对象,具有.current属性,存储着你希望持久化的数据。
2. 用法 1:获取和操作 DOM 元素
比如,你可能需要在某个操作发生时聚焦一个输入框,或者读取一个 DOM 元素的尺寸信息等。
示例:访问 DOM 元素
import React, { useRef, useEffect } from 'react';const FocusInput = () => {const inputRef = useRef(null);useEffect(() => {// 组件加载完成后,自动聚焦到输入框inputRef.current.focus();}, []);return (<div><input ref={inputRef} type="text" /></div>);
};
声明一个ref对象,通过input的ref属性将ref对象绑定,此时inputRef的current属性会指向该输入框的 DOM 元素
3. 用法 2:保持对数据的引用(不会触发重新渲染)
除了访问 DOM 元素,useRef 还可以用来存储其他可变的数据(例如计时器 ID、上一个值等),并且它不会引起组件重新渲染。
示例:持久化某个值
import React, { useState, useRef, useEffect } from 'react';const TimerComponent = () => {const [seconds, setSeconds] = useState(0);const timerRef = useRef(null);useEffect(() => {timerRef.current = setInterval(() => {setSeconds(prev => prev + 1);}, 1000);// 清理计时器return () => clearInterval(timerRef.current);}, []);return (<div><h1>{seconds} seconds</h1></div>);
};
- 在这个例子中,
timerRef用来存储计时器的 ID(一个可变的值)。即使seconds状态发生变化,timerRef的值不会改变,它仅用来引用计时器。 useRef允许我们避免因为timerRef的更新而导致不必要的组件重新渲染。
4. 用法 3:访问和持久化函数中的状态
有时你可能需要访问某个值的上一次状态。useRef 也能帮助我们存储一个值,在每次渲染时持久化下来,而不会因为它的改变导致重新渲染。
示例:记录上一个状态值
import React, { useState, useEffect, useRef } from 'react';const PreviousState = () => {const [count, setCount] = useState(0);const prevCountRef = useRef();useEffect(() => {prevCountRef.current = count;}, [count]); // 每次 `count` 变化时,更新 `prevCountRef`return (<div><h1>Current: {count}</h1><h2>Previous: {prevCountRef.current}</h2><button onClick={() => setCount(count + 1)}>Increment</button></div>);
};
- 在这个例子中,
prevCountRef用来存储count的上一个值。每次count更新时,prevCountRef.current会持有之前的值。 - 由于
useRef的特性,prevCountRef的改变不会导致组件重新渲染,所以它不会影响性能。
5. useRef 与 useState 的区别
useState:用于存储需要在 UI 上表现出来的状态。每当你调用setState更新状态时,React 会重新渲染组件。useRef:用于存储不需要触发重新渲染的状态。它的值是持久化的,不会随着组件的重新渲染而改变。
总结
useRef的.current属性在组件的整个生命周期内都保持不变。因此,您可以将它作为持久化存储来引用外部资源、DOM 元素或者数据,而不必担心它会导致组件重新渲染。- 如果你将
useRef用作数据存储时,不要把它当作普通的 React 状态来使用。因为如果你直接改变useRef的值(例如ref.current = newValue),这不会触发渲染更新,因此当你需要依赖于 UI 更新时,应该使用useState或者useReducer。
二、useNavigate
useNavigate 是 React Router v6 中的一个 Hook,用于在函数组件中进行编程式的导航。通过 useNavigate,你可以在没有用户直接点击链接的情况下进行路由跳转。它通常与事件处理函数或条件逻辑一起使用。
1. 基础概念:
useNavigate 返回一个函数,允许你在代码中进行路由跳转。该函数接受一个路径(可以是字符串)或一个包含导航选项的对象,并将页面重定向到相应的路由。
语法:
const navigate = useNavigate();
然后,你可以使用 navigate 来触发导航:
navigate('/new-path'); // 跳转到指定路径
navigate(-1); // 跳转到上一个历史记录(类似浏览器的返回按钮)
navigate('/new-path', { replace: true }); // 跳转,并替换当前的历史记录
2. 常见用法:
示例 1:基本导航
import React from 'react';
import { useNavigate } from 'react-router-dom';const HomePage = () => {const navigate = useNavigate();const goToAbout = () => {navigate('/about'); // 编程式跳转到“/about”路径};return <button onClick={goToAbout}>Go to About</button>;
};
示例 2:带参数的导航
import React from 'react';
import { useNavigate } from 'react-router-dom';const UserProfile = () => {const navigate = useNavigate();const goToProfile = (userId) => {navigate(`/profile/${userId}`); // 跳转到具体用户的个人页面};return <button onClick={() => goToProfile(123)}>Go to User 123's Profile</button>;
};
此例演示了如何将动态路径作为参数传递给 navigate,从而跳转到用户特定的页面。
3. 导航选项:
navigate 还可以接收一个对象作为第二个参数,允许你设置一些额外的导航选项,比如是否替换历史记录,或者传递状态数据。
示例 3:使用导航选项
import React from 'react';
import { useNavigate } from 'react-router-dom';const LoginPage = () => {const navigate = useNavigate();const handleLogin = () => {// 登录成功后跳转到首页,并替换当前历史记录navigate('/', { replace: true });};return <button onClick={handleLogin}>Login</button>;
};
replace:如果设置为true,则会替换当前历史记录,避免用户通过浏览器的“后退”按钮返回到此页面。state:你还可以通过state传递一些状态数据,在导航后可以通过location.state访问这些数据。
navigate('/dashboard', { state: { from: 'login' } });
4. 后退和前进:
navigate 支持通过数字来实现类似浏览器历史记录的前进和后退操作。
示例 4:模拟浏览器的后退和前进
import React from 'react';
import { useNavigate } from 'react-router-dom';const NavigationButtons = () => {const navigate = useNavigate();return (<div><button onClick={() => navigate(-1)}>Back</button> {/* 后退 */}<button onClick={() => navigate(1)}>Forward</button> {/* 前进 */}</div>);
};
navigate(-1):后退一页,类似浏览器的“后退”按钮。navigate(1):前进一页,类似浏览器的“前进”按钮。
5. 与其他 React Router 组件的结合使用:
useNavigate 可以与其他 React Router 组件(如 Route、Link 等)一起使用,来实现更复杂的导航逻辑。
示例 5:结合条件渲染导航
import React from 'react';
import { useNavigate } from 'react-router-dom';const ProtectedPage = ({ isAuthenticated }) => {const navigate = useNavigate();if (!isAuthenticated) {// 如果没有认证,重定向到登录页面navigate('/login', { replace: true });}return <div>Protected Content</div>;
};
在这个例子中,如果用户未认证,将会在渲染时进行跳转。
6. useNavigate 与 useHistory 的区别
useHistory:在 React Router v5 中使用,提供一个历史记录对象,用来进行导航。useNavigate:在 React Router v6 中替代了useHistory,提供了更加简洁的 API(没有历史对象,直接返回一个navigate函数)。
7. 总结:
useNavigate是 React Router v6 提供的用于编程式导航的 Hook,它简化了路由跳转的方式。- 使用
navigate函数,你可以轻松地进行路径跳转、替换历史记录、或者实现类似浏览器“后退”与“前进”的功能。useNavigate提供了更多灵活的导航选项,可以使路由管理更加精细和高效。
三、useLocation
useLocation 是 React Router 提供的一个钩子(hook),用于访问当前的浏览器位置对象。这可以让你获取当前的 URL 路径、查询参数、哈希值等信息,从而在函数组件中实现基于路由的动态渲染。
主要特性:
-
返回位置对象:
useLocation返回一个位置对象 (location),包含以下几个主要属性:- pathname: 当前 URL 的路径部分(例如:
/home)。 - search: 查询字符串(例如:
?id=123&name=abc)。 - hash: 哈希值(例如:
#section1)。 - state: 传递的状态对象,通常用于在页面间传递一些非 URL 参数的数据。
- pathname: 当前 URL 的路径部分(例如:
-
用途:
- 在 React 应用中动态地根据当前路径或查询参数更新 UI。
- 实现路由相关的逻辑,比如基于 URL 路径变化显示不同的内容。
-
示例:
import { useLocation } from 'react-router-dom';function MyComponent() {const location = useLocation();return (<div><p>Current Path: {location.pathname}</p><p>Query String: {location.search}</p><p>Hash: {location.hash}</p></div>); } -
动态更新:
useLocation会随着浏览器的 URL 变化自动更新。如果你想监听路由变化,可以依赖location对象的变化来触发重新渲染。 -
与
useHistory比较:useHistory主要用于程序化导航,通过访问历史对象来控制跳转。useLocation关注的是获取当前的位置信息,通常用于展示和路由状态的读取。
使用场景:
- 根据 URL 查询参数改变页面内容。
- 在某些页面上根据路径进行特定的 UI 展示(例如,导航栏高亮显示)。
- 处理哈希路由或者与后端交互时,根据不同路径做动态数据加载。
四、useSearchParams
useSearchParams 是 React Router v6 中提供的一个钩子(hook),用于读取和修改 URL 中的查询参数(即 ?key=value 的部分)。与传统的 window.location.search 不同,useSearchParams 提供了更方便的方式来处理查询字符串,同时支持 React Router 的状态管理和自动更新。
主要特性:
1.返回值: useSearchParams 返回一个数组,包含两个元素:
searchParams: 这是一个URLSearchParams对象,允许你读取、修改查询参数。setSearchParams: 这是一个函数,允许你更新查询参数并触发 URL 更新。
2.URLSearchParams 对象:
searchParams 是一个 URLSearchParams 实例,提供了多种方法来操作查询字符串
get(name): 获取某个查询参数的值(例如:searchParams.get('id'))。getAll(name): 获取某个查询参数的所有值(对于重复参数,返回一个数组)。set(name, value): 设置某个查询参数的值。has(name): 检查查询参数是否存在。delete(name): 删除某个查询参数。
3.示例代码:
import { useSearchParams } from 'react-router-dom';function MyComponent() {// 获取当前的查询参数const [searchParams, setSearchParams] = useSearchParams();// 获取特定查询参数值const id = searchParams.get('id');const name = searchParams.get('name');// 修改查询参数const updateParams = () => {setSearchParams({ id: '456', name: 'John' });};return (<div><p>Current ID: {id}</p><p>Current Name: {name}</p><button onClick={updateParams}>Update Params</button></div>);
}
4.动态更新: useSearchParams 会随着查询参数的变化自动更新组件。如果查询参数发生变化,React 会重新渲染组件。你可以使用 searchParams 来读取当前查询字符串,使用 setSearchParams 来更新它。
5.更新查询参数: 当调用 setSearchParams 时,查询参数会被更新并触发页面的重新渲染。可以传递一个新的对象(例如 { id: '456', name: 'John' })来替换当前的查询参数,也可以传递一个函数来基于当前的查询参数进行更新。
setSearchParams(prev => {// 保留现有参数,修改某个字段prev.set('id', '456');return prev;
});
使用场景:
- 控制分页和过滤器: 你可以利用查询参数(如
page、filter)来控制内容的分页或筛选。- 分享链接: 在需要共享带有查询参数的链接时,
useSearchParams允许你动态地更改查询参数并更新 URL。- 维持 URL 状态: 在多个视图间保持查询参数一致,如在搜索功能中更新查询参数,以便用户刷新页面时仍然能看到相同的结果。