useEffect не вызывается при изменении ref
При изменении переменной хука useRef, не вызывается useEffect
Переменные:
const [hiddenLayers, setHiddenLayers] = useState([])
const hiddenLayersRef = useRef([createHiddenLayerElement(1)])
Функции:
function addLayer(key) {
let hiddenLayersTemp = hiddenLayersRef.current
let elementIndex = hiddenLayersTemp.findIndex(layer => {
return layer.key === key
})
hiddenLayersTemp.splice(elementIndex + 1, 0, createHiddenLayerElement(0))
hiddenLayersRef.current = hiddenLayersTemp
}
useEffect(() => {
console.log('test')
setHiddenLayers([...hiddenLayersRef.current])
}, [hiddenLayersRef])
Но 'test' выводится только при запуске сайта, в дальнейшем, при вызове функции addLayer, useEffect не срабатывает. По какой причине так происходит и как это исправить?
Ответы (2 шт):
useRef это не state а useEffect вызывается только когда происходят изменения в state или в зависимостях state которые переданы в массив зависимостей для useEffect.
const [counter, setCounter] = useState(1);
const addCounter = () => {
setCounter(2); // эта функция вызывает `useEffect` так как `state` обновился.
}
_
const counter = useRef(1);
const addCounter = () => {
counter.current = 2; // эта не вызывает `useEffect` так как в `state` нет изменений.
}
Пример: https://codesandbox.io/s/recursing-leaf-5cimg?file=/src/App.js
useEffect срабатывает, когда изменяется значение зависимости при очередном вызове . При этом проверяет только само значение, не делая ни shallow, ни deep сравнение переданного ему объекта. Т.е. в вашем случае он случае вызовется при изменении самого hiddenLayersRef.
А useRef в свою очередь, отдает вам на каждом вызове один и тот же объект.
Если вам нужно получить вызов эффекта при изменении hiddenLayersRef.current, то так и напишите:
useEffect(() => {
console.log('test')
setHiddenLayers([...hiddenLayersRef.current])
}, [hiddenLayersRef.current])
Кроме того, для вызова эффекта нужен вызов useEffect с новыми значениями зависимости, т.е. ре-рендер компонента. Т.е. код, меняющий hiddenLayersRef.current (вызывающий ваш addLayer(key)) должен прямо или триггерить ререндер или самого компонента, или его родителя. Нет вызова - нет реренера с новыми значениями зависимости - нет нового эффекта.