接下来的一段时间,我会用于写一些好用且使用频率很高的钩子,用于记录和加强对它们的使用。
一、useCallback介绍
useCallback
是一个返回记忆函数的React钩子,该函数仅在其依赖项之一发生更改时才重新创建,否则每次调用都会返回相同的函数实例。
当您有一个组件需要将函数传递给子组件或钩子函数,但又想避免每次父组件渲染时都重新创建该函数时,就是useCallback的使用场景,此方法很有用。这有助于避免不需要的组件更新周期并提高应用程序的性能。
二、如何使用 useCallback
一个简单的demo代入代码中
App.jsx
import { useState, useCallback } from "react";
function App() {
const [count, setCount] = useState(0);
const increment = useCallback(() => {
setCount(count + 1);
}, [count]);
const reset = useCallback(() => {
setCount(0);
}, [count]);
return (
<div className="card">
<p className="count">Count: {count}</p>
<button onClick={increment}>Increment</button>
<button onClick={reset}>Reset</button>
</div>
);
}
export default App;
把APP
当做一个外部调用的函数、该函数使用钩子useState
来管理被调用的变量的状态count
。
还使用了钩子useCallback: increment
和创建了两个记忆函数reset
函数increment
是使用useCallback
和仅包含变量的依赖项列表创建的count
。说明改函数只会在值count
更改时重新创建。函数increment
作为单击按钮处理程序,单击时它会将值递增count
+1
该函数reset
的创建方式类似,使用useCallback
和仅包含变量 的依赖项列表count
。这意味着该函数只会在值count
更改时重新创建。该函数reset
用作另一个按钮的点击处理程序,当点击时,它会将 的值设置count
为 0。
useCallback
是确保功能increment
和仅在需要时reset
创建,防止每次渲染组件时都重新创建它们。这有助于避免不需要的组件更新周期并提高应用程序的性能。
三、在React中使用useCallback列出过滤器
useCallback还有一个常见的用途之一是有一个列表并且想要对该列表进行即时搜索的情况下使用
App.jsx
import "./App.css";
import { useState, useCallback } from "react";
function App() {
const [users, setUsers] = useState([
{ id: 1, name: "张三", image: "https://xxx.jpg" },
{ id: 2, name: "李四", image: "https://xxx.jpg" },
{ id: 3, name: "王五", image: "https://xxx.jpg" },
{ id: 4, name: "赵六", image: "https://xxx.jpg" },
{ id: 5, name: "小明", image: "https://xxx.jpg" },
{ id: 6, name: "小红", image: "https://xxx.jpg" },
{ id: 7, name: "小刚", image: "https://xxx.jpg" },
]);
const [filter, setFilter] = useState("");
const handleFilterChange = useCallback((event) => {
setFilter(event.target.value);
}, [filter]);
const filteredUsers = useCallback(() => {
return users.filter((user) =>
user.name.toLowerCase().includes(filter.toLowerCase())
);
}, [users, filter]);
return (
<div className="parent">
<input value={filter} onChange={handleFilterChange} placeholder="请输入搜索" />
<button onClick={() => setFilter("")}>搜索</button>
<p className="text">搜索描述</p>
<ChildComponent users={filteredUsers} />
</div>
);
}
function ChildComponent({ users }) {
return (
<ul className="child">
{users().map((user) => (
<li key={user.id}>
<img src={user.image} alt={user.name} />
<p>{user.name}</p>
</li>
))}
</ul>
);
}
export default App;
- 第一次调用列表
useState
初始化状态变量users
并返回次列表和函数setUsers
useState
再次调用以filter用空字符串初始化状态变量并返回该字符串和函数setFilter
。- 函数
handleFilterChange
是使用创建的,并且只有在值更改useCallback
时才会重新创建。filter
该函数handleFilterChange
被称为输入事件处理程序onChange
,并使用输入值更新 的filter
值。 useCallback
再次调用以创建函数filteredUsers
,该函数根据 的值过滤(用户)列表filter
。仅当或的值发生变化filteredUsers
时才会重新创建该函数。users``filter
- 该组件
App
呈现搜索条目、过滤器重置按钮和子组件ChildComponent
。的当前值filter
作为查找输入值handleFilterChange
传递,函数作为事件处理程序传递onChange
。子组件作为属性传递给函数filteredUsers
,用于呈现过滤后的卡片列表。
四、useCallback用于避免在React组件中重新创建函数
React hook允许以不可变useCallback
的方式返回一个函数,避免在每次渲染父组件时重新创建它。这在将函数作为属性传递给子组件的情况下非常有用,并且可以提高应用程序性能。
App.jsx
import { useState, useCallback } from "react";
function App() {
const [selectedType, setSelectedType] = useState(null);
const [pokemons, setPokemons] = useState([
{ id: 1, name: "Abra", type: "psychic" },
{ id: 2, name: "Bellsprout", type: "grass" },
{ id: 3, name: "Chansey", type: "normal" },
]);
const handleSelectType = useCallback((type) => {
setSelectedType(type);
}, [selectedType]);
return (
<div className="parent">
<ul className="child">
{pokemons.map((pokemon) => (
<li key={pokemon.id}>
<img src={`https://img.pokemondb.net/artwork/${pokemon.name.toLowerCase()}.jpg`} alt={pokemon.name} />
<button onClick={() => handleSelectType(pokemon.type)}>
{pokemon.name}
</button>
</li>
))}
</ul>
{selectedType && (
<DetailsComponent selectedType={selectedType} />
)}
</div>
);
}
function DetailsComponent({ selectedType }) {
return <div className="type">这是类型: {selectedType}</div>;
}
export default App;
- 创建一个名为
handleSelectType
using的回调函数useCallback
。该函数使用传递给它selectedType
的参数更新状态。type
的第二个参数useCallback
是一个依赖项数组,在本例中只是 的值selectedType
。这意味着如果 的值selectedType
没有改变,handleSelectType
则返回相同的实例并且可以在不重新渲染组件的情况下重复使用。 - 返回
JSX
,它呈现 Pokemon 列表和一个组件(DetailsComponent
如果它selectedType
有值)。 - 将
DetailsComponent
接收组件定义selectedType
为一个变量。 - 最终呈现 这是类型 xxx
小结
useCallback
上面的代码用于创建一个被调用的回调函数handleSelectType
,该函数作为 prop 传递给子组件。
当传递给的参数useCallback
(在这种情况下,只是 的值selectedType
)不变时,将handleSelectType
返回相同的实例,子组件可以重用它而无需重新渲染。这对于防止子组件在回调函数未更改时被不必要地渲染。
五、总结
React hookuseCallback
是一个有用的工具,可以避免每次渲染组件时都重新创建函数,从而保证更好的应用程序性能。
此外,通过返回不可变函数,useCallback
确保作为属性传递给子组件的函数不会随着父组件的每次渲染而改变,这在确保函数行为的一致性,在某些特定的情况下使用是很有必要的。