0

I believe its quite simple but I am not able to figureout how to replace entire object using useState and setState. Here I have the empty data:

const emptyData = {
        "foos": {},
        "bars": {}
    };

const [chartData, setChartData] = useState(emptyData);

I successfully get JSON response (response_json) from my API call which looks like below:

{
    "foos": {
        "foo1": {
            "id": "foo1",
            "foo_position": {
                "pos_x": 300,
                "pos_y": 100
            },
         },
        "foo2": {
            "id": "foo2",
            "foo_position": {
                "pos_x": 300,
                "pos_y": 300
            },
         },
        "foo3": {
            "id": "foo3",
            "foo_position": {
                "pos_x": 300,
                "pos_y": 500
            },
        }
    },
    "bars": {
        "bar1": {
            "id": "bar1"
        },
        "bar2": {
            "id": "bar2"
        }
    }
}

Now I want to replace entire chart data or foos and bars which doesnt seem not to happen:

useEffect(() => {
        async function handlePageLoad() {
            const apiURL = getDataUrl(id);
            const response = await getData(apiURL);
            if (response.status === 200) {
                const response_json = await response.json();
                setChartData(response_json);
                alert(JSON.stringify(chartData));
            }
        }
        handlePageLoad();
    }, []);

I also tried but no success:

setChartData({ ...chartData, foos: response_json.foos});

Edit: I put an alert to see if the data has been changed or not but I see following in the alert message which is similar to the initial data:

{"foos":{},"bars":{}}

Any help is much appreciated

kashi_rock
  • 539
  • 1
  • 5
  • 19
  • what is that inside `response_json`? – kyun Jun 24 '20 at 05:42
  • `useState` hook state updates aren't merged in, so if you simply want to fully replace existing state then `setChartData(response_json)` should do the trick provided it has the object shape you want. Perhaps I've misunderstood your question though. How are you validating that the state update ***isn't*** occurring? – Drew Reese Jun 24 '20 at 05:43
  • `setChartData({ ...chartData, ...response_json });` – kyun Jun 24 '20 at 05:43
  • @jinongun, the Json example I've shown in the question – kashi_rock Jun 24 '20 at 05:46
  • How do you know it's not updated? What's inside `chartData` after you set it? – tdranv Jun 24 '20 at 05:47
  • @tdranv, I can see that the chartData object is not mutated. It still has the initial data i.e. { "foos": {}, "bars": {} } – kashi_rock Jun 24 '20 at 05:50
  • Pretty obvious but... are you sure the response status is 200? – tdranv Jun 24 '20 at 05:53
  • @DrewReese, I tried that as well but no luck. State update isn't happening because I always see the initial data in chartData – kashi_rock Jun 24 '20 at 05:54
  • @tdranv, response status doesn't matter because I am can debug my code and I do see that I am trying to set valid data – kashi_rock Jun 24 '20 at 05:56
  • ***Where*** are you seeing the initial data after you update state? Where are you looking or logging it, or whatever? You haven't provided any debugging details, and "it isn't working" isn't really how it's done. For example, even a `useEffect(() => console.log(chartData), [chartData]);` will likely show state is updating or not. React-dev-tools allow you to examine state & props in real time. – Drew Reese Jun 24 '20 at 05:57
  • @DrewReeseis right. Perhaps a more complete example and explanation would help us help you :) – tdranv Jun 24 '20 at 05:59
  • @DrewReese, tdranv, please see the updated question – kashi_rock Jun 24 '20 at 06:05
  • 1
    React state updates are asynchronous, so if you're trying to console log or alert it right after calling `setChartData` it will always log the current state that hasn't been updated yet. Use the component lifecycle and check it in the ***next*** render cycle, that is when you can access the updated state. – Drew Reese Jun 24 '20 at 06:08
  • The edit to the question does not add much information. Can you provide a full example of the component or reproduce it in a sandbox? – tdranv Jun 24 '20 at 06:16
  • 1
    @DrewReese. I see the problem now. I didn't add a variable in useeffect. Added a refresh key did the trick. if you post your comment as answer, I can mark my question as answered. Thank you Drew and tdranv. – kashi_rock Jun 24 '20 at 06:20
  • i think @Drew Reese is right, the result of logging the state immediately after updating it will report the stale data, because it hasn't actually been merged yet. – elemetrics Jun 24 '20 at 06:23

1 Answers1

0

I think you just need to wait for the mutation to be merged. try the following to log the state after it has been updated

useEffect(() => {
    async function handlePageLoad() {
        const apiURL = getDataUrl(id);
        const response = await getData(apiURL);
        if (response.status === 200) {
            const response_json = await response.json();
            setChartData(response_json);
            // alert(JSON.stringify(chartData));
        }
    }
    handlePageLoad().then(() => alert(JSON.stringify(chartData)));
}, [])
elemetrics
  • 330
  • 1
  • 8