I am trying to learn reactjs but I am stuck on a strange state bug. My page fetches a sequence record from the server and I am trying to update the page when the response arrives. But for some reason sequence here isn't updated.
The getSequence: before and getSequence: after lines both show the stale value, but the response.data shows the fetched record.
const [sequence, setSequence] = useState(initialSequenceState);
useEffect(() => {
const getSequence = (id) => {
SequenceDataService.get(id)
.then(response => {
console.log(`useEffect.getSequence: before ${JSON.stringify(sequence)}`)
setSequence(response.data);
console.log(`useEffect.getSequence: got ${JSON.stringify(response.data)}`)
console.log(`useEffect.getSequence: after ${JSON.stringify(sequence)}`)
})
.catch(e => {
console.error(e);
});
}
getSequence(routeParams.id);
}, []);
The two lines that print out sequence show the same output. But response.data contains the correct value.
What am I doing wrong?
Here is a code-reduced repro with the output below:
import React, { useContext, createContext, useState, useEffect } from "react";
import SequenceDataService from "../services/sequence"
import {Link, useParams, useNavigate} from "react-router-dom";
import * as Realm from "realm-web";
import SequenceCanvas from "./sequence-canvas";
import { SequenceContext } from './sequence-context'
function Sequence() {
const routeParams = useParams();
console.log(JSON.stringify(routeParams))
const navigate = useNavigate();
const app = new Realm.App({id: "powermad-hsulz"});
const initialSequenceState = {
name: "New Sequence",
text: "edm, acid",
user_name: app.currentUser.profile.email,
user_id: app.currentUser.id,
steps: [
{note: 60, velocity: 127, gateLength: 0.9, },
{note: 60, velocity: 60, gateLength: 0.9, },
{note: 72, velocity: 100, gateLength: 0.9, },
],
numSteps: 3,
length: 5,
tempo: 120.0,
division: 16,
reviews: [],
};
const [sequence, setSequence] = useState(initialSequenceState);
useEffect(() => {
const getSequence = (id) => {
SequenceDataService.get(id)
.then(response => {
console.log(`useEffect.getSequence: before ${JSON.stringify(sequence)}`)
setSequence(response.data);
console.log(`useEffect.getSequence: got ${JSON.stringify(response.data)}`)
console.log(`useEffect.getSequence: after ${JSON.stringify(sequence)}`)
})
.catch(e => {
console.error(e);
});
}
getSequence(routeParams.id);
}, []);
return (
<SequenceContext.Provider value={sequence}>
<div>
{sequence.name}
<div>
<SequenceCanvas sequence={sequence}/>
</div>
</div>
</SequenceContext.Provider>
);
}
export default Sequence;
Output:
useEffect.getSequence: before {"name":"New Sequence","text":"edm, acid","user_name":"me@me.me","user_id":"62de9859630cf0df56a9f6b8","steps":[{"note":60,"velocity":127,"gateLength":0.9}],"numSteps":3,"length":5,"tempo":120,"division":16,"reviews":[]}
sequence.js:39 useEffect.getSequence: got {"_id":"62de9861e9bde9f8ce59bb48","name":"New Sequence by Me","text":"edm, acid","user_name":"me@me.me","user_id":"62de9859630cf0df56a9f6b8","steps":[{"note":60,"velocity":127,"gateLength":0.9},{"note":60,"velocity":60,"gateLength":0.9},{"note":72,"velocity":100,"gateLength":0.9},{"note":60,"velocity":100,"gateLength":0.9},{"note":60,"velocity":100,"gateLength":0.9},{"note":60,"velocity":100,"gateLength":0.9}],"tempo":120,"length":"7","numSteps":"5","division":16,"reviews":[]}
sequence.js:40 useEffect.getSequence: after {"name":"New Sequence","text":"edm, acid","user_name":"me@me.me","user_id":"62de9859630cf0df56a9f6b8","steps":[{"note":60,"velocity":127,"gateLength":0.9}],"numSteps":3,"length":5,"tempo":120,"division":16,"reviews":[]} sequence.js:11