React自定义Hook如何正确封装可复用的状态逻辑
自定义Hook是React中复用组件逻辑的重要方式。通过将状态和副作用逻辑封装成可复用的函数,可以避免组件间重复代码,保持代码整洁。
一、自定义Hook的基本规则
自定义Hook必须以 use 开头,这是React识别Hook的约定。它返回一个数组或对象,包含状态和操作函数。
// 正确的自定义Hook命名
function useMyLogic() {
// 逻辑实现
return [state, setState];
}
二、创建自定义Hook的步骤
1. 识别 可复用的逻辑
在现有组件中寻找重复的状态管理或副作用逻辑。例如,多个组件都需要获取数据或处理表单输入。
2. 提取 逻辑到独立函数
将重复逻辑从组件中移出,创建新的函数。确保函数只包含状态和副作用,不包含UI渲染。
// 示例:提取数据获取逻辑
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
fetch(url)
.then(response => response.json())
.then(setData)
.catch(setError)
.finally(() => setLoading(false));
}, [url]);
return { data, loading, error };
}
3. 返回 状态和操作函数
根据需要返回状态值、操作函数或对象。确保返回值清晰,便于调用组件使用。
4. 在组件中 使用自定义Hook
像使用内置Hook一样调用自定义Hook,获取返回的状态和函数。
function UserProfile({ userId }) {
const { data, loading, error } = useFetch(`/api/users/${userId}`);
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return <div>{data.name}</div>;
}
三、最佳实践
1. 参数化 逻辑
通过参数使Hook更灵活,适应不同场景。
function useLocalStorage(key, initialValue) {
const [storedValue, setStoredValue] = useState(() => {
try {
const item = window.localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
} catch (error) {
return initialValue;
}
});
const setValue = value => {
try {
setStoredValue(value);
window.localStorage.setItem(key, JSON.stringify(value));
} catch (error) {
console.error(error);
}
};
return [storedValue, setValue];
}
2. 管理 依赖关系
在useEffect中正确声明依赖数组,避免不必要的重新执行。
useEffect(() => {
// 依赖url和options
}, [url, options]);
3. 保持 纯净
自定义Hook不应包含UI渲染逻辑,只处理状态和副作用。
4. 测试 Hook
编写单元测试确保Hook行为正确,使用React Testing Library或Jest。
test('useFetch fetches data', async () => {
global.fetch = jest.fn(() =>
Promise.resolve({
json: () => Promise.resolve({ name: 'Test' })
})
);
const { result, waitForNextUpdate } = renderHook(() => useFetch('/api/test'));
expect(result.current.loading).toBe(true);
await waitForNextUpdate();
expect(result.current.data).toEqual({ name: 'Test' });
});
四、常见场景示例
1. 表单处理Hook
function useForm(initialValues) {
const [values, setValues] = useState(initialValues);
const handleChange = e => {
const { name, value } = e.target;
setValues(prev => ({ ...prev, [name]: value }));
};
const resetForm = () => setValues(initialValues);
return [values, handleChange, resetForm];
}
2. 窗口尺寸Hook
function useWindowSize() {
const [size, setSize] = useState({
width: window.innerWidth,
height: window.innerHeight
});
useEffect(() => {
const handleResize = () => setSize({
width: window.innerWidth,
height: window.innerHeight
});
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
return size;
}
通过遵循这些步骤和最佳实践,可以创建出高效、可复用的自定义Hook,提升React应用的代码质量和开发效率。

暂无评论,快来抢沙发吧!