0

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

ohthepain
  • 2,004
  • 3
  • 19
  • 30
  • The `sequence` is a `const`. Why would you expect it to change? – Bergi Jul 25 '22 at 14:13
  • 1
    `sequence` is a local const, and calling `setSequence` does *not* change its value. Instead, `setSequence` requests that the component be rerendered. On that new render, a new local variable will be created with the new value, but your code from the old render can't access that. If you'd like to verify that the component rerendered, put a log statement in the body of the component. – Nicholas Tower Jul 25 '22 at 14:13
  • Thanks @NicholasTower The light came on. – ohthepain Jul 25 '22 at 21:13

0 Answers0