I'm a beginner and I feel like I'm making a fundamental mistake somewhere. I'm making a simple React component to get notes to play in order using Tone JS. I can't update the notes with a button. When I click a button to check they're updated it seems the state has been changed but the repeat
function still plays the 'old notes'. Where am I going wrong?
// create a synth
let synth = new Tone.Synth({
attack: 0.5,
decay: 0.5,
sustain: 1,
release: 5,
volume: -10
}).toDestination()
const Main = () => {
// set state with note values
const [noteValue, setNoteValue] = useState([
{ note: 'C4', properties: ''},
{ note: 'C4', properties: ''}
])
const [isPlaying, setIsPlaying] = useState(false)
// start/stop transport
const startStop = () => {
if (!isPlaying) Tone.start()
setIsPlaying(!isPlaying)
!isPlaying ? Tone.Transport.start() : Tone.Transport.stop()
}
Tone.Transport.bpm.value = 140
// song loop function - always displays the same notes after state change
let index = 0
function repeat(time){
const position = index % noteValue.length
const synthNote = noteValue[position]
console.log(noteValue)
synth.triggerAttackRelease(synthNote.note, time)
index++
}
// set the transport on the first render
useEffect(() => {
Tone.Transport.scheduleRepeat((time) => {
repeat(time)
}, '4n')
},[])
// the "change note values" button doesn't change them inside the repeat function
return <>
<button onClick={() => setNoteValue([
{ note: 'C5', properties: ''},
{ note: 'C5', properties: ''}
])}>Change Note Values</button>
<button onClick={() => console.log(noteValue)}>Check note values</button>
<button onClick={() => startStop()}>Start/Stop</button>
</>
Thank you.