1. Использование useRef вместо useState для неконтролируемых обновлений
Многие новички используют useState
, когда им нужно хранить значения между рендерами. Однако, если обновление состояния не требует повторного рендера компонента, лучше использовать useRef
.
Пример:
import { useState, useRef } from "react";
function Example() {
const [count, setCount] = useState(0);
const countRef = useRef(0);
const incrementState = () => setCount(count + 1);
const incrementRef = () => countRef.current++;
console.log("Rendered", countRef.current);
return (
<div>
<p>State: {count}</p>
<button onClick={incrementState}>Increment State</button>
<button onClick={incrementRef}>Increment Ref</button>
</div>
);
}
Здесь при обновлении countRef.current
не происходит повторного рендера компонента.
2. Ленивое создание состояния
Если значение useState
требует сложных вычислений, его можно инициализировать лениво:
const [data, setData] = useState(() => expensiveCalculation());
Это предотвратит лишние вызовы функции expensiveCalculation()
при каждом ререндере.
3. Мемоизация функций с useCallback
При передаче функций в дочерние компоненты стоит использовать useCallback
, чтобы предотвратить ненужные перерендеры:
import { useCallback } from "react";
function Parent() {
const handleClick = useCallback(() => {
console.log("Clicked");
}, []);
return <Child onClick={handleClick} />;
}
Без useCallback
при каждом ререндере Parent
создавалась бы новая функция handleClick
, что могло бы вызвать ненужный ререндер Child
.
4. Оптимизация ререндеров с React.memo
Если компонент получает одни и те же пропсы, но ререндерится, можно использовать React.memo
:
const MemoizedComponent = React.memo(({ value }) => {
console.log("Rendered");
return <p>{value}</p>;
});
Теперь MemoizedComponent
не будет ререндериться, если value
не изменилось.
5. Управление состоянием с useReducer
Если у вас сложная логика изменения состояния, useReducer
может заменить useState
:
import { useReducer } from "react";
const reducer = (state, action) => {
switch (action.type) {
case "increment":
return { count: state.count + 1 };
case "decrement":
return { count: state.count - 1 };
default:
return state;
}
};
function Counter() {
const [state, dispatch] = useReducer(reducer, { count: 0 });
return (
<div>
<p>Count: {state.count}</p>
<button onClick={() => dispatch({ type: "increment" })}>+</button>
<button onClick={() => dispatch({ type: "decrement" })}>-</button>
</div>
);
}
Этот метод делает управление состоянием более предсказуемым и удобным при сложных изменениях.
Эти пять хаков помогут вам улучшить навыки в React.js, сократить количество лишних ререндеров и писать более оптимизированный код. Используйте их в своих проектах и делитесь с другими разработчиками!
Комментарии