Сначала ознакомьтесь с моим введением в React hooks, если вы новичок в них.
Один реактивный крючок, который я иногда использую, это обратный вызов пользователя .
import React, { useCallback } from 'react'Этот хук полезен, когда у вас есть компонент с дочерним компонентом, который часто перерисовывается, и вы передаете ему обратный вызов:
import React, { useState, useCallback } from 'react'
const Counter = () => {
const [count, setCount] = useState(0)
const [otherCounter, setOtherCounter] = useState(0)
const increment = () => {
setCount(count + 1)
}
const decrement = () => {
setCount(count - 1)
}
const incrementOtherCounter = () => {
setOtherCounter(otherCounter + 1)
}
return (
<>
Count: {count}
)
}
ReactDOM.render( , document.getElementById('app'))Проблема здесь в том, что каждый раз, когда счетчик обновляется, все 3 функции создаются заново.
Вы можете визуализировать это, создав экземпляр заданной структуры данных и добавив в нее каждую функцию. Почему Set? потому что в нем хранятся только уникальные элементы, что в нашем случае означает разные (уникальные экземпляры) функции.
import React, { useState, useCallback } from 'react'
const functionsCounter = new Set()
const Counter = () => {
const [count, setCount] = useState(0)
const [otherCounter, setOtherCounter] = useState(0)
const increment = () => {
setCount(count + 1)
}
const decrement = () => {
setCount(count - 1)
}
const incrementOtherCounter = () => {
setOtherCounter(otherCounter + 1)
}
functionsCounter.add(increment)
functionsCounter.add(decrement)
functionsCounter.add(incrementOtherCounter)
alert(functionsCounter)
return (
<>
Count: {count}
)
}
ReactDOM.render( , document.getElementById('app'))Если вы попробуете этот код, вы увидите, что оповещение увеличивается на 3 за раз.
Вместо этого должно произойти следующее: если вы увеличите один счетчик, все функции, связанные с этим счетчиком, должны быть созданы заново.
Если другое значение состояния не изменилось, его не следует трогать.
Теперь, в большинстве случаев, это не является большой проблемой, если только вы не передаете множество различных функций, все изменяющих несвязанные биты данных, которые, как доказано, сильно снижают производительность вашего приложения.
Если это проблема, вы можете использовать обратный вызов пользователя .
Вот как мы это делаем. Вместо:
const increment = (() => {
setCount(count + 1)
})
const decrement = (() => {
setCount(count - 1)
})
const incrementOtherCounter = (() => {
setOtherCounter(otherCounter + 1)
})Ты оборачиваешь все эти звонки в:
const increment = useCallback(() => {
setCount(count + 1)
}, [count])
const decrement = useCallback(() => {
setCount(count - 1)
}, [count])
const incrementOtherCounter = useCallback(() => {
setOtherCounter(otherCounter + 1)
}, [otherCounter])Убедитесь, что вы добавили этот массив в качестве второго параметра в используйте обратный вызов() с необходимым состоянием.
Теперь, если вы попытаетесь щелкнуть один из счетчиков, будут повторно созданы только функции, связанные с состоянием, которое изменяется.
Вы можете попробовать этот пример в Codepen:
Видишь ручку Реагировать на перехват обратного вызова пользователя автор: Флавио Копес ( @флавиокопы ) на Кодовое соединение .
Оригинал: “https://flaviocopes.com/react-hook-usecallback/”