При перезаписи массива он перезаписывает себя в 2 раза больше. Как это исправить ? 'keyup' event react js
Всем привет! Я не давно начал изучать react ) Создаю свою мини игру по персонажу из Dota2 "Invoker".
Суть в том что бы прожать правильную комбо сфер для заклинаний. Я записываю это комбо в useState массив const [ spells, setSpells] = useState(['', '', ''])
для того что бы отображать какие сферы уже были нажаты. Когда срабатывает функция changeShperes массив перезаписывается в 2 раза больше. Будто за ним тянется его история перезаписей. Как это исправить ? И за за чего это возникает ?
import React, { useState } from 'react';
import Spell from '../UI/Spell/Spell';
// ======= Styles ======
import cl from './ActiveSpheres.module.scss';
const ActiveSpheres = ({ binds }) => {
// binds = {
// 'firstSpell': 'q',
// 'secondSpell': 'w',
// 'thirdSpell': 'e',
// 'fourthSpell': 'd',
// 'fifthSpell': 'f',
// 'sixthSpell': 'r',
// };
const [ spells, setSpells] = useState(['', '', ''])
const changeShperes = (e) => {
let arr = spells;
let sphere = '';
if ( e.key === binds.firstSpell ) {
// ======= quas ======
if ( spells.length === 3) {
arr.shift()
}
sphere = 'quas'
} else if ( e.key === binds.secondSpell ) {
// ======= wex ======
if ( spells.length === 3) {
arr.shift()
}
sphere = 'wex'
} else if ( e.key === binds.thirdSpell ) {
// ======= exort ======
if ( spells.length === 3) {
arr.shift()
}
sphere = 'exort'
}
setSpells([...arr, sphere])
}
document.addEventListener('keyup', changeShperes)
return (
<div className={cl.inner}>
<div className={cl['active-spheres']}>
{
spells.map((sphere, indx) => (
<Spell
key={sphere + indx}
pathImg={sphere}
/>
))
}
</div>
</div>
);
};
export default ActiveSpheres;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
Ответы (2 шт):
Я бы посоветовал переделать следующим образом:
const changeShperes = (e) => {
let sphere = '';
if ( e.key === binds.firstSpell ) {
sphere = 'quas'
} else if ( e.key === binds.secondSpell ) {
sphere = 'wex'
} else if ( e.key === binds.thirdSpell ) {
sphere = 'exort'
}
setSpells(spells => {
return [sphere, ...spells.slice(0, 2)];
})
}
Я понял, чего не хватало в моем коде. Это удаление event, чтобы он не плодился при каждом новом ренедере компонента.
Кому интересно можете почитать:
const [ spells, setSpells] = useState(['', '', ''])
const changeShperes = (e) => {
let sphere = '';
if ( e.key === binds.firstSpell ) {
sphere = 'quas'
} else if ( e.key === binds.secondSpell ) {
sphere = 'wex'
} else if ( e.key === binds.thirdSpell ) {
sphere = 'exort'
}
if ( spells.length === 3 ) {
spells.shift()
}
setSpells([...spells, sphere])
}
// === componentDidMount()
useEffect(() => {
document.addEventListener('keyup', changeShperes)
}, [])
// === componentWillUnmount()
useEffect(() => {
document.addEventListener('keyup', changeShperes)
return () => {
document.removeEventListener('keyup', changeShperes)
}
}, [spells])
return (
<div className={cl.inner}>
<div className={cl['active-spheres']}>
{
spells.map((sphere, indx) => (
<Spell
key={sphere + indx}
pathImg={sphere}
/>
))
}
</div>
</div>
);
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>