簡體   English   中英

將 function 傳遞給 React 中的無狀態功能組件時遇到問題

[英]Trouble passing a function to a stateless functional component in React

我正在為一個 freeCodeCamp 項目在 React 中創建一個鼓機。 我渲染了按鈕,但無法獲得播放音頻的按鈕。

我創建了一個無狀態功能組件,它遍歷包含音頻 url 和其他一些細節的對象數組,創建一個鍵盤來播放聲音。 播放音頻的 function 在應用程序組件中,我將 function 作為道具傳遞給鍵盤。

我在控制台中收到 object 錯誤,無法弄清楚它來自哪里。 CodePen 在這里( https://codepen.io/cpmcclure/pen/qBXGNpw ),我也復制了下面的代碼。 任何想法都會有所幫助。 提前致謝!

 class App extends React.Component { constructor(props) { super(props); this.playSound = this.playSound.bind(this); } playSound = (key) => { const audio = document.getElementById(key); audio.currentTime = 0; audio.play(); } render() { return( <Keyboard play={this.playSound}/> ) } } const Keyboard = ({playSound}) => { return TR66.map(sound => { return (<button class="drum-pad" id={sound.id} onClick={() => playSound(sound.key)}> <audio class="clip" id={sound.key} src={sound.url}/> <div>{sound.key}</div> </button>) }); } const TR66 = [ { keyCode: 81, key: 'Q', id: 'Bass Drum', url: 'https://sampleswap.org/samples-ghost/DRUMS%20(FULL%20KITS)/DRUM%20MACHINES/Roland%20TR-66/15[kb]66-bd-01.wav.mp3' }, { keyCode: 87, key: 'W', id: 'Snare', url: 'https://sampleswap.org/samples-ghost/DRUMS%20(FULL%20KITS)/DRUM%20MACHINES/Roland%20TR-66/14[kb]66-sd-01.wav.mp3' }, { keyCode: 69, key: 'E', id: 'Hi Hat 1', url: 'https://sampleswap.org/samples-ghost/DRUMS%20(FULL%20KITS)/DRUM%20MACHINES/Roland%20TR-66/6[kb]66-hh-01-or.wav.mp3' }, { keyCode: 65, key: 'A', id: 'Hi Hat 2', url: 'https://sampleswap.org/samples-ghost/DRUMS%20(FULL%20KITS)/DRUM%20MACHINES/Roland%20TR-66/5[kb]66-hh-08.wav.mp3' }, { keyCode: 83, key: 'S', id: 'Hi Hat Open 1', url: 'https://sampleswap.org/samples-ghost/DRUMS%20(FULL%20KITS)/DRUM%20MACHINES/Roland%20TR-66/33[kb]66-hho-01-or.wav.mp3' }, { keyCode: 68, key: 'D', id: 'Hi Hat Open 2', url: 'https://sampleswap.org/samples-ghost/DRUMS%20(FULL%20KITS)/DRUM%20MACHINES/Roland%20TR-66/37[kb]66-hho-04.wav.mp3' }, { keyCode: 90, key: 'Z', id: 'Wood Block Low', url: 'https://sampleswap.org/samples-ghost/DRUMS%20(FULL%20KITS)/DRUM%20MACHINES/Roland%20TR-66/26[kb]66-per-08.wav.mp3' }, { keyCode: 88, key: 'X', id: 'Wood Block High', url: 'https://sampleswap.org/samples-ghost/DRUMS%20(FULL%20KITS)/DRUM%20MACHINES/Roland%20TR-66/12[kb]66-per-03.wav.mp3' }, { keyCode: 67, key: 'C', id: 'Rim', url: 'https://sampleswap.org/samples-ghost/DRUMS%20(FULL%20KITS)/DRUM%20MACHINES/Roland%20TR-66/11[kb]66-rim-01.wav.mp3' } ] ReactDOM.render(<App />, document.getElementById("drum-machine"))
 button { width: 5rem; height: 5rem; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script> <div id="drum-machine"> </div>

命名似乎有誤:組件 function 是const Keyboard = ({playSound}) => {但它是用<Keyboard play={this.playSound}/>創建的。 正確的匹配是<Keyboard playSound={this.playSound}/>

此外, class應該是className並且所有數組子元素都需要具有唯一鍵。

我建議始終使用功能組件。 沒有 state 是必需的,如果是,您可以使用useState掛鈎

我建議將音頻對象附加到您的架子鼓元素。 將套件數據自包含在自己的數據結構中可以減輕渲染<audio>元素的組件的負擔,然后通過 id 查找它們只是為了播放剪輯。 沒有必要通過 DOM 來 go —— 相反,你可以簡單地說kit[i].audio.play()kit是一個通用套件,我們在這里用TR66設置填充)一旦你設置了kit[i] = new Audio(kit[i].url)

如果需要,您可以將文檔偵聽器用於鍵觸發器,或者將該偵聽器單獨附加到鼓機組件。 這說明在套件中包含音頻對象可以輕松地從多個位置播放它們,盡管我意識到它在您當前的代碼上有點領先。 如果不需要,請刪除useEffect

 const App = () => <DrumMachine kit={TR66} />; const DrumPad = ({text, onPlay}) => ( <button className="drum-pad" onClick={onPlay}> <div>{text}</div> </button> ); const DrumMachine = ({kit}) => { const playAudio = audio => { audio.currentTime = 0; audio.play(); }; React.useEffect(() => { const listener = e => { const drum = kit.find(({key}) => key.toLowerCase() === e.key.toLowerCase() ); drum && playAudio(drum.audio); }; document.addEventListener("keydown", listener); return () => document.removeEventListener("keydown", listener); }, []); return ( <div> {kit.map(({key, id, audio}) => <DrumPad key={id} text={key} onPlay={() => playAudio(audio)} /> )} </div> ); }; const TR66 = [ { keyCode: 81, key: 'Q', id: 'Bass Drum', url: 'https://sampleswap.org/samples-ghost/DRUMS%20(FULL%20KITS)/DRUM%20MACHINES/Roland%20TR-66/15[kb]66-bd-01.wav.mp3' }, { keyCode: 87, key: 'W', id: 'Snare', url: 'https://sampleswap.org/samples-ghost/DRUMS%20(FULL%20KITS)/DRUM%20MACHINES/Roland%20TR-66/14[kb]66-sd-01.wav.mp3' }, { keyCode: 69, key: 'E', id: 'Hi Hat 1', url: 'https://sampleswap.org/samples-ghost/DRUMS%20(FULL%20KITS)/DRUM%20MACHINES/Roland%20TR-66/6[kb]66-hh-01-or.wav.mp3' }, { keyCode: 65, key: 'A', id: 'Hi Hat 2', url: 'https://sampleswap.org/samples-ghost/DRUMS%20(FULL%20KITS)/DRUM%20MACHINES/Roland%20TR-66/5[kb]66-hh-08.wav.mp3' }, { keyCode: 83, key: 'S', id: 'Hi Hat Open 1', url: 'https://sampleswap.org/samples-ghost/DRUMS%20(FULL%20KITS)/DRUM%20MACHINES/Roland%20TR-66/33[kb]66-hho-01-or.wav.mp3' }, { keyCode: 68, key: 'D', id: 'Hi Hat Open 2', url: 'https://sampleswap.org/samples-ghost/DRUMS%20(FULL%20KITS)/DRUM%20MACHINES/Roland%20TR-66/37[kb]66-hho-04.wav.mp3' }, { keyCode: 90, key: 'Z', id: 'Wood Block Low', url: 'https://sampleswap.org/samples-ghost/DRUMS%20(FULL%20KITS)/DRUM%20MACHINES/Roland%20TR-66/26[kb]66-per-08.wav.mp3' }, { keyCode: 88, key: 'X', id: 'Wood Block High', url: 'https://sampleswap.org/samples-ghost/DRUMS%20(FULL%20KITS)/DRUM%20MACHINES/Roland%20TR-66/12[kb]66-per-03.wav.mp3' }, { keyCode: 67, key: 'C', id: 'Rim', url: 'https://sampleswap.org/samples-ghost/DRUMS%20(FULL%20KITS)/DRUM%20MACHINES/Roland%20TR-66/11[kb]66-rim-01.wav.mp3' } ]; TR66.forEach(({url}, i) => { TR66[i].audio = new Audio(url); }); ReactDOM.render(<App />, document.getElementById("app"));
 button { width: 5rem; height: 5rem; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script> <div id="app"></div>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM