0

I'm trying to fetch a list of departments from an url in a react native application

import React,{ useState,useEffect} from 'react';
import { StyleSheet, LogBox,View,Text } from 'react-native';




export default function App() {
var [department,setDepartment]=useState([])
const token = /* my token here */

  const getDepartments=()=>{  
    const url = /*my api's url here*/

      return fetch(url, {
          method: 'GET',
          headers: { "Authorization": "Bearer" + token ,
          'Accept': 'application/json',
          'Content-Type':'application/json'
      }
      })
          .then(response => response.json())
           .then(data=>console.log(data)) // returns the correct data
          .catch(error => console.error(error))
  }

   const getdepartment = async () => {
            await getDepartments().then((res) => //here lays the problem
              {res.map((p, key) => {
                department.push({
                  name: p.name,
                  id: p.id,
                });
              });
            });
          };

          useEffect(() => {

            getdepartment();

          }, []);

  return (
  <View>
  <Text>
             {department[0]}
                            </Text>

              </View>
  )
}

here res in the getdepartment() function is undefined despite the getDepartments() function returning correct data from the url

  • You don't need to use `await` if you're going to use `.then` Just use `const response = await getDepartments();` then do all the logic on the response variable, so `response.map ...` – Ameer Jul 23 '21 at 14:42
  • Remove `.then(data=>console.log(data))` or change it to `.then(data=>{ console.log(data); return data; })` – ponury-kostek Jul 23 '21 at 14:43
  • @ponury-kostek I tried both .. still doesn't work – cold programmmer Jul 23 '21 at 14:45
  • 2
    You sure `res` is an array? Map doesn't exist on objects – Imanpal Singh Jul 23 '21 at 14:45
  • I think @skrrrt and @ponury's comment should help you figure what's wrong. First, check that the data is actually an array. Second, make sure to return the data in your promise by `.then(data=>{ console.log(data); return data; })` (note that the curly braces is necessary). By `console.log` but not return anything, you are not getting any value from that promise chain (thus the `undefined`) – Bao Huynh Lam Jul 23 '21 at 14:58
  • @BaoHuynhLam but I made a return before the fetch – cold programmmer Jul 23 '21 at 15:00
  • that `return` before the fetch is returning the promise chain. Inside the actual promise chain, you then did `.then(data => {return console.log(data)})`. Because `console.log` returns nothing, you effectively did `.then(data => undefined)`. Therefore, as the last `then` returns nothing, the entire promise chain will resolve to nothing. – Bao Huynh Lam Jul 23 '21 at 15:03
  • my other apis worked without the need of the second return – cold programmmer Jul 23 '21 at 15:07
  • It is actually not the second return. The [arrow function shorthand](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions) `() => something` (without curly braces) is actually shorthand for `() => {return something}`. Therefore, `.then(response => response.json())` is actually `then(response => {return response.json()}`. In each of the `then`, you need to return the data that the next `then` will access. Your "other apis" probably might have worked because they did not return `console.log` in the middle of the promise chain. – Bao Huynh Lam Jul 23 '21 at 15:19
  • @coldprogrammmer I just found this post that may explain this better than I do: https://stackoverflow.com/questions/44439596/why-is-value-undefined-at-then-chained-to-promise – Bao Huynh Lam Jul 24 '21 at 13:24

2 Answers2

0

You are not returning a value from getDepartments, just a simple console.log.

You can convert the function in async/await:

const getDepartments = async () => {  
    const url = /*my api's url here*/
    try {
      const response = await fetch(url, {
          method: 'GET',
          headers: { "Authorization": "Bearer" + token ,
          'Accept': 'application/json',
          'Content-Type':'application/json'
      }
      })
      return await response.json();
      } catch(e){
        // error
      }
  }

or return a value from your function:

const getDepartments=()=>{  
    const url = /*my api's url here*/

      return fetch(url, {
          method: 'GET',
          headers: { "Authorization": "Bearer" + token ,
          'Accept': 'application/json',
          'Content-Type':'application/json'
      }
      })
          .then(response => response.json())
          .catch(error => console.error(error))
  }
Francesco Clementi
  • 1,874
  • 4
  • 13
  • 28
0

If you are returning the result of the fetch then just return the result obtained from it, the issue is along with fetch, the response is also handled and the complete thing post to that is being returned which is not the result so you just need to skip this line .then(data=>console.log(data))

const getDepartments=()=>{  
const url = /*my api's url here*/

  return fetch(url, {
      method: 'GET',
      headers: { "Authorization": "Bearer" + token ,
      'Accept': 'application/json',
      'Content-Type':'application/json'
  }
  }).then(response =>  response.json()).catch(error => 
     console.error(error))
   
  }

// Here after fetching the result you can map the data

  const getdepartment = async () => {
        await getDepartments().then((res) => 
          {res.map((p, key) => {
            department.push({
              name: p.name,
              id: p.id,
            });
          });
        });
      };
Ruchi Tiwari
  • 261
  • 1
  • 4