避免 React Hooks 频繁渲染导致性能问题
- useMemo:
- 作用:
useMemo
用于记忆一个值,只有当它的依赖项发生变化时才会重新计算。这可以避免在每次渲染时都进行昂贵的计算。
- 示例:
import React, { useMemo } from'react';
const ExpensiveCalculation = ({ a, b }) => {
const result = useMemo(() => {
// 模拟昂贵的计算
let sum = 0;
for (let i = 0; i < 1000000; i++) {
sum += i;
}
return a + b + sum;
}, [a, b]);
return <div>{result}</div>;
};
export default ExpensiveCalculation;
- 原理:
useMemo
接收一个回调函数和依赖项数组。只有依赖项数组中的值发生变化时,才会重新执行回调函数并返回新的值。否则,直接返回上一次记忆的值。
- useCallback:
- 作用:
useCallback
用于记忆一个函数,只有当它的依赖项发生变化时才会重新创建该函数。这在将函数作为 prop 传递给子组件,且子组件依赖于函数引用相等性(例如在 shouldComponentUpdate
或 React.memo 中)时非常有用,可以避免不必要的子组件重新渲染。
- 示例:
import React, { useCallback } from'react';
const ChildComponent = React.memo(({ onClick }) => {
return <button onClick={onClick}>Click me</button>;
});
const ParentComponent = () => {
const handleClick = useCallback(() => {
console.log('Button clicked');
}, []);
return <ChildComponent onClick={handleClick} />;
};
export default ParentComponent;
- 原理:
useCallback
接收一个回调函数和依赖项数组。与 useMemo
类似,只有依赖项变化时才会重新创建回调函数,否则返回上一次记忆的函数引用。
自定义 Hook 处理表单验证逻辑
- 设计思路:
- 首先,定义一个自定义 Hook,该 Hook 应该能够管理表单的状态,例如输入值和验证状态。
- 提供验证函数,这些函数可以根据不同的规则(如必填、邮箱格式等)对输入值进行验证。
- 当输入值发生变化时,触发验证并更新验证状态。
- 代码实现:
import { useState, useEffect } from'react';
const useFormValidation = (initialValue = '', validators = []) => {
const [value, setValue] = useState(initialValue);
const [isValid, setIsValid] = useState(true);
const [errorMessage, setErrorMessage] = useState('');
const handleChange = (e) => {
const inputValue = e.target.value;
setValue(inputValue);
let isValid = true;
let errorMsg = '';
validators.forEach((validator) => {
const { isValid: check, errorMessage } = validator(inputValue);
if (!check) {
isValid = false;
errorMsg = errorMessage;
}
});
setIsValid(isValid);
setErrorMessage(errorMsg);
};
useEffect(() => {
let isValid = true;
let errorMsg = '';
validators.forEach((validator) => {
const { isValid: check, errorMessage } = validator(value);
if (!check) {
isValid = false;
errorMsg = errorMessage;
}
});
setIsValid(isValid);
setErrorMessage(errorMsg);
}, [value]);
return {
value,
isValid,
errorMessage,
handleChange
};
};
// 示例验证函数
const requiredValidator = (value) => {
return {
isValid: value.trim()!== '',
errorMessage: 'This field is required'
};
};
const emailValidator = (value) => {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return {
isValid: emailRegex.test(value),
errorMessage: 'Please enter a valid email'
};
};
export { useFormValidation, requiredValidator, emailValidator };
- 使用示例:
import React from'react';
import { useFormValidation, requiredValidator, emailValidator } from './useFormValidation';
const FormComponent = () => {
const { value: emailValue, isValid: emailIsValid, errorMessage: emailErrorMessage, handleChange: emailHandleChange } = useFormValidation('', [requiredValidator, emailValidator]);
return (
<div>
<label>Email:</label>
<input type="email" value={emailValue} onChange={emailHandleChange} />
{!emailIsValid && <span style={{ color:'red' }}>{emailErrorMessage}</span>}
</div>
);
};
export default FormComponent;