繁体   English   中英

React hooks - 当 state 更改为相同的值时,如何强制 useEffect 运行?

[英]React hooks - how to force useEffect to run when state changes to the same value?

所以我正在构建一个鼓垫类型的应用程序,几乎所有东西都在工作,除了这个。

编辑:如果有人想看的话,把整个东西放在codesandbox上:codesandbox.io/s/sleepy-darwin-jc9b5?file=/src/App.js

const [index, setIndex] = useState(0);
const [text, setText] = useState("");
const [theSound] = useSound(drumBank[index].url)   

function playThis(num) {
  setIndex(num)
}

useEffect(()=>{
  if (index !== null) {
    setText(drumBank[index].id);
    theSound(index);
    console.log(index)
  }
}, [index])

当我按下按钮时,索引更改为与按钮关联的值,然后 useEffect 挂钩从该索引处的数组播放声音。 但是,当我多次按下同一个按钮时,它只会播放一次,因为当索引更改为相同的值时,useState 不会重新渲染应用程序。

我希望能够多次按下同一个按钮并让应用程序重新渲染,因此每次按下按钮时都会运行 useEffect。 谁能帮助我如何做到这一点?

您是否考虑过将这些离散的 state 变量(值类型)组合成单个引用类型 state object?

而不是在索引更改时设置文本的效果,您只需同时设置整个 state。

只要您确保这是一个新的对象/引用,那么效果就会触发。 然后效果器只负责播放基于当前 state 的声音。

这是我可以从您的沙盒中得出的结论。

  1. 根据文档,每个useSound只是一个声音,因此当尝试将索引更新到音库以通过 React state 使用时,播放的声音将始终延迟至少一个渲染周期。 我建议创建一个新的自定义挂钩来封装您的 9 鼓声音。

    useDrumBank使用鼓组数组并将 9 个鼓声实例化为一个数组。

     const useDrumBank = (drumbank) => { const [drum0] = useSound(drumbank[0].url); const [drum1] = useSound(drumbank[1].url); const [drum2] = useSound(drumbank[2].url); const [drum3] = useSound(drumbank[3].url); const [drum4] = useSound(drumbank[4].url); const [drum5] = useSound(drumbank[5].url); const [drum6] = useSound(drumbank[6].url); const [drum7] = useSound(drumbank[7].url); const [drum8] = useSound(drumbank[8].url); return [drum0, drum1, drum2, drum3, drum4, drum5, drum6, drum7, drum8]; };
  2. 更新组件逻辑以将drumBank数组传递给新的自定义挂钩。

     const sounds = useDrumBank(drumBank);

这是完整的代码:

function App() {
  useEffect(() => {
    document.addEventListener("keypress", key);

    return () => document.removeEventListener("keypress", key);
  }, []);

  const [text, setText] = useState("");
  const sounds = useDrumBank(drumBank);

  function playThis(index) {
    drumBank[index]?.id && setText(drumBank[index].id);
    sounds[index]();
  }

  function key(e) {
    const index = drumBank.findIndex((drum) => drum.keyTrigger === e.key);
    index !== -1 && playThis(index);
  }

  return (
    <div id="drum-machine" className="drumpad-container">
      <div id="display" className="drumpad-display">
        <p>{text}</p>
      </div>
      <button className="drum-pad" id="drum-pad-1" onClick={() => playThis(0)}>
        Q
      </button>
      <button className="drum-pad" id="drum-pad-2" onClick={() => playThis(1)}>
        W
      </button>
      <button className="drum-pad" id="drum-pad-3" onClick={() => playThis(2)}>
        E
      </button>
      <button className="drum-pad" id="drum-pad-4" onClick={() => playThis(3)}>
        A
      </button>
      <button className="drum-pad" id="drum-pad-5" onClick={() => playThis(4)}>
        S
      </button>
      <button className="drum-pad" id="drum-pad-6" onClick={() => playThis(5)}>
        D
      </button>
      <button className="drum-pad" id="drum-pad-7" onClick={() => playThis(6)}>
        Z
      </button>
      <button className="drum-pad" id="drum-pad-8" onClick={() => playThis(7)}>
        X
      </button>
      <button className="drum-pad" id="drum-pad-9" onClick={() => playThis(8)}>
        C
      </button>
    </div>
  );
}

演示

编辑 react-hooks-how-to-force-useeffect-to-run-when-state-changes-to-the-same-value

使用说明

加载后立即没有声音

为用户着想,浏览器不允许网站在用户与它们进行交互(例如,通过点击某物)之前产生声音。 在用户点击、轻敲或触发某些东西之前,不会产生声音。

让按键持续工作似乎是一个问题,我没有立即想到解决方案,但至少此时按钮点击工作并且声音同步播放。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM