使用useState的自定义react钩子始终重置为其初始值

时间:2020-08-13 16:34:47

标签: javascript reactjs react-hooks setstate

我正在尝试创建一个自定义react钩子,以将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);
  };

它起作用了,Q的element.id用Q:true和其他所有false返回状态。但是,如果我再次运行该函数,它将Q重置为其初始值false,而新元素为true。有人可以指出我正确的方向吗?我尝试了设置播放状态和初始化状态的不同组合,但是我感觉自己只是在拍摄蓝光,这里我想念的是什么?

编辑:我正在使用该状态以isPlaying的形式呈现truefalse的组件列表

  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 个答案:

答案 0 :(得分:0)

我认为您访问状态不正确,但是我不确定,因为您并没有全部代码来查看如何访问状态。

我从您的代码中重新创建了一个小例子

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,如果立即访问该状态,则会得到旧的{{1 }},您会发现state仍为假,而从Q内部读取值将给出新的真实值