#javascript #reactjs #react-hooks
#javascript #reactjs #реагирующие крючки
Вопрос:
Я не понимаю, почему я получаю бесконечный цикл в useClick Я вижу, что я изменяю значение состояния внутри useEffect с помощью setVal, но useEffect должен работать только на onClick, как указано во втором параметре. Я думал, что это потому, что параметр onClick, который я передаю, запоминается, но обратный вызов не вызывается (я проверил это с помощью console.log(‘go set’)
function useClick(onClick, setVal, val) {
React.useEffect(() => {
console.log('Click');
setVal(val 1);
}, [onClick]);
}
const Home = () => {
const [val, setVal] = React.useState(0);
const incrementOnClick = React.useCallback(() => {
console.log('go set');
setVal(val 1);
} , [setVal, val]);
useClick(incrementOnClick, setVal, val);
return <div>
<div>{val}</div>
<button onClick={incrementOnClick}>Click me</button>
</div>
}
Комментарии:
1. Я думаю, что цикл вызван вызовом
useClick
insideHome
Component:Home
вызываетuseClick
, внутриuseClick
вы изменяетеval
свойствоHome
, таким образом,Home
компонент ` повторно отображается, таким образом, функцияHome
вызывается снова, таким образом,useClick
выполняется снова.. И вот цикл2. Глядя на ваш код, я не уверен, что вы пытаетесь сделать. Помните, что при каждом
Home
рендеринге вы будете получать другой экземплярincrementOnClick
, поэтому передача его в качестве последнего параметраuseEffect
ничего не даст.3. Да, именно поэтому я использую функцию useCallback, чтобы избежать
Ответ №1:
val
и setVal
будет меняться при каждом рендеринге, что, в свою очередь, приведет к тому, incrementOnClick
что станет ссылкой на новую функцию, и ваш useClick
эффект будет вызываться всегда.
Вместо этого вы могли бы предоставить функцию в качестве первого аргумента setVal
. Эта функция получает текущее значение val
в качестве аргумента и возвращает новое значение. Таким образом, incrementOnClick
всегда будет одна и та же функция.
const { useEffect, useState, useCallback } = React;
function useClick(onClick, setVal, val) {
useEffect(() => {
console.log("Click");
setVal(val 1);
}, [onClick]);
}
const Home = () => {
const [val, setVal] = useState(0);
const incrementOnClick = useCallback(() => {
console.log("go set");
setVal(val => val 1);
}, []);
useClick(incrementOnClick, setVal, val);
return (
<div>
<div>{val}</div>
<button onClick={incrementOnClick}>Click me</button>
</div>
);
};
ReactDOM.render(<Home />, document.getElementById("root"));
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>
Приведенный выше код показывает, как можно избежать бесконечного цикла, и может быть полезен для экспериментов, но в большинстве случаев в этом нет необходимости. Вместо этого вы могли бы написать такую же функциональность, как эта:
const { useState } = React;
const Home = () => {
const [val, setVal] = useState(1);
return (
<div>
<div>{val}</div>
<button onClick={() => setVal(val 1)}>Click me</button>
</div>
);
};
ReactDOM.render(<Home />, document.getElementById("root"));
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>
Ответ №2:
Глядя на то, что вы пытаетесь сделать, я считаю, что вам не хватает одной из самых полезных функций Hooks amp; React, а именно композиции.
Вот пример того, что вы сделали, но простое создание другого компонента с именем <IncrementButton/>
, на мой взгляд, просто упрощает понимание / отладку кода. Пользовательские хуки великолепны, но я считаю, что для этого это неподходящий инструмент..
const { useEffect, useState } = React;
const IncrementButton = props => {
const {val, setVal, children} = props;
return <button
onClick={() => setVal(val 1)}
>{children}</button>;
}
const Home = () => {
const [val, setVal] = useState(0);
return (
<div>
<div>{val}</div>
<IncrementButton val={val} setVal={setVal}>
Click me
</IncrementButton>
</div>
);
};
ReactDOM.render(<Home />, document.getElementById("root"));
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>
Комментарии:
1. Конечно, этот вопрос был в основном для того, чтобы спросить, понимаю ли я хуки. Конечно, последняя кнопка будет выглядеть разделенной, как вы написали. Спасибо