Home > Mobile >  Can't use the data from API when app just starts
Can't use the data from API when app just starts

Time:11-04

My data is undefined when the app is started but after the refresh, the data comes perfectly.

For startup It gives me [Unhandled promise rejection: TypeError: Object.entries requires that input parameter not be null or undefined]

But after the refresh, the data comes perfectly and everything working.

This is part of my data

Object {
  "attributes": Object {
    "htmlName": null,
    "id": 0,
    "items": Array [
      Object {
        "htmlName": "r_1",
        "name": "m2 (Brüt)",
        "numeric": true,
        "options": Object {},
        "order": 0,
        "required": true,
      },
      Object {
        "htmlName": "r_2",
        "name": "m2 (Net)",
        "numeric": true,
        "options": Object {},
        "order": 0,
        "required": true,
      },
      Object {
        "htmlName": "r_164",
        "name": "Arsa Alanı (m2)",
        "numeric": true,
        "options": Object {},
        "order": 0,
        "required": true,
      },
      Object {
        "htmlName": "a_137",
        "name": "Oda Sayısı",
        "numeric": false,
        "options": Object {
          "12": "1 0",
          "13": "1 1",
          "14": "1.5 1",
          "15": "2 0",
          "16": "2 1",
          "17": "2.5 1",
          "18": "2 2",
          "19": "3 1",
          "20": "3.5 1",
          "21": "3 2",
          "22": "4 1",
          "226": "0 1",
          "23": "4.5 1",
          "24": "4 2",
          "25": "4 3",
          "26": "4 4",
          "27": "5 1",
          "28": "5 2",
          "29": "5 3",
          "30": "5 4",
          "31": "6 1",
          "32": "6 2",
          "33": "6 3",
          "34": "7 1",
          "35": "7 2",
          "36": "7 3",
          "37": "8 1",
          "38": "8 2",
          "39": "8 3",
          "40": "8 4",
          "41": "9 1",
          "42": "9 2",
          "43": "9 3",
          "44": "9 4",
          "45": "9 5",
          "46": "9 6",
          "47": "10 1",
          "48": "10 2",
          "49": "10 Üzeri",
        },
        "order": 0,
        "required": true,
      },

api.js

  export const getData = function () {
  return axios
    .get(
      "blabla",
      {
        headers: {
          Authorization: `blabla`,
        },
      }
    )
    .then((json) => {
      if (json && json.status === 200) {
        //console.log(json);
        return json.data;
      }
    })
    .catch((e) => {
      console.log(e);
    });
};

App.js

const [data, setData] = useState({});
  const [roomValue, setRoomValue] = useState(null);

  const [roomCount, setRoomCount] = useState([]);
  const [isFocus, setIsFocus] = useState(false);

  useEffect(() => {
    getDataFunc();
    //setDropdown(data.attributes.items[3].options);
  }, []);

  const getDataFunc = async () => {
    const res = await getData();
    //console.log(res);
    setData(res);
    console.log(data);
  };

  function setDropdown(query) {
    const response = query;
    try {
      const entries = Object.entries(response);
      const tempArray = [];
      for (let i = 0; i < entries.length; i  ) {
        var key;
        var value;
        (key = entries[i][0]), (value = entries[i][1]);
        tempArray.push({ key: value, value: key });
      }
      setRoomCount(tempArray);
      //console.log(roomCount);
    } catch (error) {
      //console.log(error);
    }
  }

How can I fix that ?

CodePudding user response:

Add a seperate useEffect to check wheather the data has been set and then only set the dropdown values

   useEffect(() => {
    getDataFunc();
   }, []);

  useEffect(() => {
    if(data && data.attributes?.items[3]){
       setDropdown(data.attributes.items[3].options);
    }
  }, [data]);

  const getDataFunc = async () => {
    const res = await getData();
    //console.log(res);
    setData(res);
    console.log(data);
  };

CodePudding user response:

It seems like the error is caused by the attributes property being empty when you try to access it. But when you assign them one by one then it loads because the data is loaded per nested property before assigning it to the variable. Means it hasn't fully loaded yet

const response = data.attributes.items[3].options;

It outputs an error because attributes is undefined. So it's not an object, therefore, attributes.items is considered invalid

// sample

const data = {
  /* attributes: {
    items: {
      1: {
        options: 'option1'
      },
      2: {
        options: 'option2'
      },
      3: {
       options: 'option3'
      }
    }
  } */
}


const specificData = data.attributes.items[3].options

console.log(specificData) // 

So one solution would be using the optional chaining operator to avoid the error, it's just basically a question mark (?) after the object you are trying to access.

The response would be then 'undefined'. That way even if the attributes is empty or not, data will be assigned to the response constant then you can just add some more checking outside of that.

    // sample

    const data = {
      /* attributes: {
        items: {
          1: {
            options: 'option1'
          },
          2: {
            options: 'option2'
          },
          3: {
           options: 'option3'
          }
        }
      } */
    }


    const specificData = data.attributes?.items[3].options

    console.log(specificData) // outputs undefined instead of an error

Let me know if this works btw. maybe you could provide the actual api or maybe a sample api endpoint so we could test it directly. Or maybe the full code?

I've encoutered this before though I'm not 100% sure this is all I've done. But for the error I'm sure the optional chaining operator will prevent it

CodePudding user response:

Try calling getData inside an async function and wait for the process to complete like this in your App.js

const [data, setData] = useState([]);
const [roomCount, setRoomCount] = useState([]);

useEffect(() => {
    getDataFunc()
}, []);

const getDataFunc = async() => {
    await getData(setData);
    const response = data;
    console.log(response);
    const entries = Object.entries(response);
    const tempArray = [];
    for (let i = 0; i < entries.length; i  ) {
      var key;
      var value;
      (key = entries[i][0]), (value = entries[i][1]);
      tempArray.push({ key: value, value: key });
    }

    setRoomCount(tempArray);
    console.log(roomCount);
}

note: The best practice is not to directly pass the setData function to getData api call instead return the response from api and assign the response in main code like below

const response = await getData();
setData(response)

CodePudding user response:

From what I see, your data.attributes has undefined value. Please double-check everything, it is technically impossible to get data directly if data.attributes is undefined

  • Related