Пользовательский перехват реакции с постоянным сбросом useState к его начальному значению

#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. Привет, спасибо за ваш ответ, я отредактировал свой первоначальный вопрос, чтобы вы могли видеть, где я получаю доступ к этому состоянию.