#javascript #reactjs #react-hooks #setstate
#javascript #reactjs #перехваты реакции #setstate
Вопрос:
Я пытаюсь создать пользовательский перехват реакции для сохранения состояния 9 элементов в объекте с помощью true или false.
let pads = {
Q: false,
W: false,
E: false,
A: false,
S: false,
D: false,
F: false,
Z: false,
X: false,
C: false,
};
export default () => {
const [padsPlaying, setPadsPlaying] = useState(pads);
return {
padsPlaying,
setPlayState: (element, state) => {
setPadsPlaying({ ...state, [element]: true });
},
};
};
В моем компоненте я импортирую перехват и вызываю его следующим образом:
const { padsPlaying, setPlayState } = usePlayState();
const playSound = (element) => {
// do some other stuff and in the end:
setPlayState(element.id, padsPlaying);
};
Это работает, an element.id of Q
возвращает состояние с Q:true
и все остальное false
. Однако, если я снова запускаю функцию, она сбрасывается Q
до своего начального значения false
, и новым элементом является true
. Может ли кто-нибудь указать мне правильное направление? Я пробовал разные комбинации настройки состояния воспроизведения и инициализации состояния, но я чувствую, что я просто стреляю в пустоту, чего мне здесь не хватает?
РЕДАКТИРОВАТЬ: я использую это состояние для отображения списка компонентов с реквизитом isPlaying, который должен быть либо true
, либо false
const makePads = preset[0].sounds.map((sound, i) => (
<DrumPad
key={sound.id}
id={sound.name}
name={sound.name}
source={sound.source}
trigger={sound.trigger}
isPlaying={padsPlaying[i]}
/>
));
РЕШАЕМАЯ
Я запутался в том, где я использовал старое состояние, теперь перехват выглядит так, и он работает 🙂
export default () => {
const [padsPlaying, setPadsPlaying] = useState(initialPads);
const setPlayState = (id) => {
setPadsPlaying((state) => {
console.log(id);
return { ...state, [id]: true };
});
};
return [padsPlaying, setPlayState];
};
Ответ №1:
Я думаю, вы неправильно обращаетесь к состоянию, но я не уверен, потому что вы не написали весь код, чтобы увидеть, как вы обращаетесь к состоянию.
Я воссоздал небольшой пример из вашего кода
let pads = {
Q: false,
W: false,
};
const usePlayState = () => {
const [padsPlaying, setPadsPlaying] = useState(pads);
const setPlayState = (element, state) => {
setPadsPlaying({ ...state, [element]: true });
}
return [
padsPlaying,
setPlayState,
];
};
function Testme() {
const [padsPlaying, setPlayState] = usePlayState();
useEffect(() => {
console.log(padsPlaying) // the proper way to access the new updated state is here
})
return (<div>
<button onClick={() => {
setPlayState('Q', padsPlaying);
// console.log(padsPlaying); // => Q still false because you still have the old stale state
}}>
Q
</button>
<button onClick={() => {
setPlayState('W', padsPlaying);
// console.log(padsPlaying); // => W still false because you still have the old stale state
}}>
W
</button>
</div>)
}
и я указал вам, где находится правильный способ доступа к новому состоянию, которое находится в useEffect
более эквивалентном ComponentDidMount
состоянии, если вы немедленно обращаетесь к состоянию, вы получите старое, state
и вы обнаружите, что Q
все еще false при чтении значения изнутри useEffect
даст новое реальное значение
Комментарии:
1. Привет, спасибо за ваш ответ, я отредактировал свой первоначальный вопрос, чтобы вы могли видеть, где я получаю доступ к этому состоянию.