在 React 中,自定义 Hooks 是一种非常强大的工具,它允许你将组件逻辑提取到可重用的函数中。这使得代码更加模块化、清晰,并且能够在多个组件之间共享状态或副作用。
下面是一些常见的自定义 Hooks 以及如何封装它们的示例。
1. 封装 useFetch
自定义 Hook
useFetch
是一个常见的自定义 Hook,用于封装数据获取逻辑。它可以接收一个 URL,并返回加载状态、获取的数据和可能的错误信息。
import { useState, useEffect } from 'react';
const useFetch = (url) => {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error('Network response was not ok');
}
const result = await response.json();
setData(result);
} catch (err) {
setError(err);
} finally {
setLoading(false);
}
};
fetchData();
}, [url]);
return { data, loading, error };
};
export default useFetch;
使用示例:
import React from 'react';
import useFetch from './useFetch';
const DataDisplay = () => {
const { data, loading, error } = useFetch('https://jsonplaceholder.typicode.com/posts/1');
if (loading) return <p>Loading...</p>;
if (error) return <p>Error: {error.message}</p>;
return (
<div>
<h1>{data.title}</h1>
<p>{data.body}</p>
</div>
);
};
export default DataDisplay;
2. 封装 useLocalStorage
自定义 Hook
useLocalStorage
自定义 Hook 用于将状态持久化到浏览器的 localStorage
中。这在需要持久化用户设置或缓存数据时非常有用。
import { useState } from 'react';
const useLocalStorage = (key, initialValue) => {
const [storedValue, setStoredValue] = useState(() => {
try {
const item = window.localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
} catch (error) {
console.log(error);
return initialValue;
}
});
const setValue = (value) => {
try {
const valueToStore = value instanceof Function ? value(storedValue) : value;
setStoredValue(valueToStore);
window.localStorage.setItem(key, JSON.stringify(valueToStore));
} catch (error) {
console.log(error);
}
};
return [storedValue, setValue];
};
export default useLocalStorage;
使用示例:
import React from 'react';
import useLocalStorage from './useLocalStorage';
const Counter = () => {
const [count, setCount] = useLocalStorage('count', 0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
<button onClick={() => setCount(0)}>Reset</button>
</div>
);
};
export default Counter;
3. 封装 useToggle
自定义 Hook
useToggle
是一个简单的自定义 Hook,用于切换布尔值。这在实现开关、显示/隐藏功能时非常方便。
import { useState } from 'react';
const useToggle = (initialValue = false) => {
const [value, setValue] = useState(initialValue);
const toggle = () => {
setValue((prevValue) => !prevValue);
};
return [value, toggle];
};
export default useToggle;
使用示例:
import React from 'react';
import useToggle from './useToggle';
const ToggleComponent = () => {
const [isToggled, toggle] = useToggle();
return (
<div>
<p>{isToggled ? 'ON' : 'OFF'}</p>
<button onClick={toggle}>Toggle</button>
</div>
);
};
export default ToggleComponent;
4. 封装 useDebounce
自定义 Hook
useDebounce
自定义 Hook 用于处理防抖操作,可以在用户输入后延迟执行某个操作。这在搜索框、输入框等场景下非常有用。
import { useState, useEffect } from 'react';
const useDebounce = (value, delay) => {
const [debouncedValue, setDebouncedValue] = useState(value);
useEffect(() => {
const handler = setTimeout(() => {
setDebouncedValue(value);
}, delay);
return () => {
clearTimeout(handler);
};
}, [value, delay]);
return debouncedValue;
};
export default useDebounce;
使用示例:
import React, { useState } from 'react';
import useDebounce from './useDebounce';
const Search = () => {
const [searchTerm, setSearchTerm] = useState('');
const debouncedSearchTerm = useDebounce(searchTerm, 500);
useEffect(() => {
if (debouncedSearchTerm) {
// 这里可以进行搜索请求
console.log('Searching for:', debouncedSearchTerm);
}
}, [debouncedSearchTerm]);
return (
<input
type="text"
placeholder="Search..."
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
/>
);
};
export default Search;
5. 封装 usePrevious
自定义 Hook
usePrevious
自定义 Hook 用于获取组件中某个状态的前一个值。
import { useEffect, useRef } from 'react';
const usePrevious = (value) => {
const ref = useRef();
useEffect(() => {
ref.current = value;
}, [value]);
return ref.current;
};
export default usePrevious;
使用示例:
import React, { useState } from 'react';
import usePrevious from './usePrevious';
const CounterWithPrevious = () => {
const [count, setCount] = useState(0);
const previousCount = usePrevious(count);
return (
<div>
<p>Current Count: {count}</p>
<p>Previous Count: {previousCount}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
};
export default CounterWithPrevious;
这些示例展示了如何封装常用的自定义 Hooks,帮助你在项目中复用逻辑,提高开发效率。自定义 Hooks 可以根据具体的业务逻辑进行扩展和修改,充分利用它们的灵活性来简化代码。