最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Attempting to use a loading state to stop undefined data - Stack Overflow

programmeradmin4浏览0评论

So I know that the data used in a setState call won't be updated until the next render and have looked up plenty to figure out what to do about that. The best solution I kept finding was to use a loading state and set it to true and rendering a loading screen until the data is fetched. But for some reason I can't seem to get this to work for me. I'm curious if there is something I'm missing about this or what is going on but when the paramData is passed to the LineGraph, it never renders out and is undefined when I log it in a useEffect, though it logs again after and has the data. Though if I remove the ? in the line graph data?.entries, there is an undefined error. Here is the component doing the fetch and loading (I originally had a setState for loading, and would set it to true at the start of the useEffect, and set to false at the end to no avail):

import { useState, useEffect } from "react";
import LineGraph from "../components/Graphs/LineGraph";
import TopNav from "../components/General/TopNav";
import Card from "../layout/Card";
import { fetchParamData } from "../utils/dataHandler";

const Parameters = () => {

  const [paramData, setParamData] = useState([]);

  useEffect(() => {
    const fetchParameters = async () => {
      const data = await fetchParamData();
      setParamData(data)
    }

    fetchParameters();
  },[]);

  if(!paramData || paramData === undefined) {
    return (
      <section className="loading">
        <p>
          Loading
        </p>
      </section>
    )
  }

  return (
    <>
      <TopNav />
      <Card>
        <LineGraph data={paramData[0]} />
      </Card>
    </>
  );
}

export default Parameters;

and the LineGraph just in case it's needed:

import { useEffect, useRef } from "react";
import { LineChart, Line, CartesianGrid, XAxis, YAxis, Tooltip } from "recharts";
import colorVars from "../../modules/sassVars.module.scss";


const LineGraph = ({ data }) => {

  useEffect(() => {
    console.log(data);
  },[data]);

  return (
    <div>
      <LineChart width={400} height={200} data={data?.entries} margin={{ top: 5, right: 20, bottom: 5, left: 0 }}>
        <Line type="monotone" dataKey="parameterLevel" stroke={colorVars.primary20} strokeWidth="5" />
        <CartesianGrid stroke="#ccc" />
        <XAxis />
        <YAxis />
      </LineChart>
    </div>
  );
}

export default LineGraph;

I feel like there is something I'm missing about this, but I'm unsure as to what. I can't seem to find a good answer elsewhere with my searching. Any help would be great! Thanks

So I know that the data used in a setState call won't be updated until the next render and have looked up plenty to figure out what to do about that. The best solution I kept finding was to use a loading state and set it to true and rendering a loading screen until the data is fetched. But for some reason I can't seem to get this to work for me. I'm curious if there is something I'm missing about this or what is going on but when the paramData is passed to the LineGraph, it never renders out and is undefined when I log it in a useEffect, though it logs again after and has the data. Though if I remove the ? in the line graph data?.entries, there is an undefined error. Here is the component doing the fetch and loading (I originally had a setState for loading, and would set it to true at the start of the useEffect, and set to false at the end to no avail):

import { useState, useEffect } from "react";
import LineGraph from "../components/Graphs/LineGraph";
import TopNav from "../components/General/TopNav";
import Card from "../layout/Card";
import { fetchParamData } from "../utils/dataHandler";

const Parameters = () => {

  const [paramData, setParamData] = useState([]);

  useEffect(() => {
    const fetchParameters = async () => {
      const data = await fetchParamData();
      setParamData(data)
    }

    fetchParameters();
  },[]);

  if(!paramData || paramData === undefined) {
    return (
      <section className="loading">
        <p>
          Loading
        </p>
      </section>
    )
  }

  return (
    <>
      <TopNav />
      <Card>
        <LineGraph data={paramData[0]} />
      </Card>
    </>
  );
}

export default Parameters;

and the LineGraph just in case it's needed:

import { useEffect, useRef } from "react";
import { LineChart, Line, CartesianGrid, XAxis, YAxis, Tooltip } from "recharts";
import colorVars from "../../modules/sassVars.module.scss";


const LineGraph = ({ data }) => {

  useEffect(() => {
    console.log(data);
  },[data]);

  return (
    <div>
      <LineChart width={400} height={200} data={data?.entries} margin={{ top: 5, right: 20, bottom: 5, left: 0 }}>
        <Line type="monotone" dataKey="parameterLevel" stroke={colorVars.primary20} strokeWidth="5" />
        <CartesianGrid stroke="#ccc" />
        <XAxis />
        <YAxis />
      </LineChart>
    </div>
  );
}

export default LineGraph;

I feel like there is something I'm missing about this, but I'm unsure as to what. I can't seem to find a good answer elsewhere with my searching. Any help would be great! Thanks

Share Improve this question edited Feb 18 at 4:04 Drew Reese 203k17 gold badges237 silver badges268 bronze badges asked Feb 17 at 4:59 TapialjTapialj 3432 gold badges3 silver badges11 bronze badges 1
  • 2 The default value is empty array useState([]), so if(!paramData || paramData === undefined) will always be false, use useState(undefined) instead. – Shuo Commented Feb 17 at 5:56
Add a comment  | 

4 Answers 4

Reset to default 2

There two things to look at first check the fetchParamData() is return a array of data, if its return correct useEffect(()=>{},[]) is executes at the very first render on the entire component. when it runs LineGraph is renders but the fetchParamData() data is not received yet and also SetState is asynchronous.you might get chance if you assign a save data to new array and set the new Array to SetState().

const fetchParameters = async () => {
  const data = await fetchParamData();
  let array=[...data]
  setParamData(array)
}
 if(paramData.length===0) {
    return (
      <section className="loading">
        <p>
          Loading
        </p>
      </section>
    )
  }

  return (
    <>
      <TopNav />
      <Card>
        {paramaData.length>0 && <LineGraph data={paramData[0]} />}
      </Card>
    </>
  );

check paramData length for loading, also ensure that paramData is not empty before rendering LineGraph

The below code is unreachable since an empty array will not match here.

...
if (!paramData || paramData === undefined) {
...

Please correct it to this:

...
if (paramData.length === 0) {
...

if the below statement returns a non empty array, then rest of codes will work fie.

...
const data = await fetchParamData();
...
import { useState, useEffect } from "react";
import LineGraph from "../components/Graphs/LineGraph";
import TopNav from "../components/General/TopNav";
import Card from "../layout/Card";
import { fetchParamData } from "../utils/dataHandler";

const Parameters = () => {
  const [paramData, setParamData] = useState([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const fetchParameters = async () => {
      setLoading(true);
      try {
        const data = await fetchParamData();
        setParamData(data);
      } catch (error) {
        console.error("Error fetching data:", error);
      } finally {
        setLoading(false);
      }
    };

    fetchParameters();
  }, []);

  useEffect(() => {
    console.log("Updated paramData:", paramData);
  }, [paramData]);

  if (loading || paramData.length === 0) {
    return (
      <section className="loading">
        <p>Loading...</p>
      </section>
    );
  }

  return (
    <>
      <TopNav />
      <Card>
        <LineGraph data={paramData[0]} />
      </Card>
    </>
  );
};

export default Parameters;
发布评论

评论列表(0)

  1. 暂无评论