У меня есть функциональный компонент, использующий зацепки:
function Component(props) {
const [ items, setItems ] = useState([]);
// In a callback Hook to prevent unnecessary re-renders
const handleFetchItems = useCallback(() => {
fetchItemsFromApi().then(setItems);
}, []);
// Fetch items on mount
useEffect(() => {
handleFetchItems();
}, []);
// I want this effect to run only when 'props.itemId' changes,
// not when 'items' changes
useEffect(() => {
if (items) {
const item = items.find(item => item.id === props.itemId);
console.log("Item changed to " item.name);
}
}, [ items, props.itemId ])
// Clicking the button should NOT log anything to console
return (
<Button onClick={handleFetchItems}>Fetch items</Button>
);
}
Компонент получает несколько items
при монтировании и сохраняет их в состояние.
Компонент получает itemId
prop (от React Router).
Всякий раз, когда меняется props.itemId
, я хочу, чтобы это вызывало эффект, в этом случае регистрируя его на консоли.
Проблема в том, что, посколькуэффект также зависит от items
, эффект также будет запускаться всякий раз, когда изменяется items
, например, когда items
повторно выбирается нажатием кнопки.
Это можно исправить, сохранив предыдущийprops.itemId
в отдельной переменной состояния и сравнение двух, но это похоже на хак и добавляет шаблон.Используя классы компонентов, это решается путем сравнения текущего и предыдущего реквизита в componentDidUpdate
, но это невозможно при использовании функциональных компонентов, что является обязательным требованием для использования крючков.
Что является лучшимспособ вызвать эффект, зависящий от нескольких параметров, только при изменении одного из параметров?
PS.Крючки - это что-то новое, и я думаю, что мы все изо всех сил стараемся понять, как правильно с ними работать, поэтому, если мой способ мышления об этом кажется вам неправильным или неудобным, пожалуйста, укажите на это.