【问题标题】:Custom react hook with useState always resetting to its initial value带有 useState 的自定义反应钩子始终重置为其初始值
【发布时间】:2020-08-13 16:34:47
【问题描述】:

我正在尝试创建一个自定义反应钩子,用于将 9 个元素的状态保存在一个对象中,无论是真还是假。

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];
};

【问题讨论】:

    标签: javascript reactjs react-hooks setstate


    【解决方案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,您会发现从useEffect 内部读取值时,Q 仍然为 false 将给出新的真实值

    【讨论】:

    • 您好,感谢您的回复,我编辑了原始问题,以便您查看我访问该状态的位置。
    猜你喜欢
    • 1970-01-01
    • 2023-04-01
    • 2021-05-20
    • 2020-07-05
    • 2021-03-19
    • 2022-01-21
    • 1970-01-01
    • 2021-11-03
    • 2021-02-08
    相关资源
    最近更新 更多