#javascript #reactjs #callback #frontend #memoization
#javascript #reactjs #обратный вызов #интерфейс #запоминание
Вопрос:
У меня есть плата функциональных компонентов, и в возвращаемом JSX я просматриваю 2D-массив и печатаю кучу квадратов, и я передаю обработчик плюс некоторую дополнительную информацию в каждый из них. Я хотел предотвратить их повторный рендеринг, если Квадрат получает те же реквизиты, поэтому компонент Square находится в методе React.memo(). В компоненте платы, где я обрабатываю обновления платы, у меня есть обработчик с useCallback, поэтому я не передаю совершенно новую функцию при повторных отправках.
Чего я не понимаю, так это того, что в теле clickHandler у меня всегда есть доступ к свежему обновленному 2D-массиву, вызываемому на board, но я никогда не получаю измененного игрока, он всегда остается равным 1. Тем не менее, само состояние переключается на 2 и наоборот. Если я передам player в качестве зависимости, все мои 300 квадратов будут перенаправлены повторно.
Я не передаю состояние в качестве опоры квадрату, я просто сопоставляю плату и передаю значения с самой платы.
Итак, мой вопрос в том, почему у меня есть доступ к обновленной плате в clickHandler, но не к проигрывателю. Например, когда я нажимаю на один из своих квадратов, он всегда принимается игроком1, который используется по умолчанию.
Ссылка на весь репозиторий (это всего лишь несколько компонентов): https://github.com/TreblaCodes/react-connect5
Спасибо
const [player, setPlayer] = useContext(PlayerContext)
const [board, setBoard] = useContext(PositionsContext)
const clickHandler = useCallback((x,y) => {
let board_copy = [...board]
board_copy[y][x] = player;
setBoard(board_copy)
console.log(board) //updated
setPlayer(player === 1 ? 2 : 1)
console.log(player) // stays at 1
},[])
Ответ №1:
Просто попробуйте передать player и board во второй параметр useCallback . Затем всякий раз, когда игрок или доска будут изменены, вы получите новый экземпляр обратного вызова.
Вот так:
const [player, setPlayer] = useContext(PlayerContext)
const [board, setBoard] = useContext(PositionsContext)
const clickHandler = useCallback((x,y) => {
let board_copy = [...board]
board_copy[y][x] = player;
setBoard(board_copy)
console.log(board) //updated
setPlayer(player === 1 ? 2 : 1)
console.log(player) // stays at 1
},[player, board])
Комментарии:
1. Это затем заставляет все мои квадраты повторно отображать… Без каких-либо зависимостей плата в clickHandler является обновленной версией, но не игроком
2. Причина, по которой ваша плата обновляется, заключается в том, что вы нарушаете принцип неизменности. Эта строка «board_copy[y] [x] = player;» изменяет исходный объект.
3. пусть board_copy = […board], должен сделать копию
4. @Albert.Hadacek это не делает глубокую копию. Каждая запись ссылается на один и тот же объект. Итак, board_copy[y] === board[y]