user14751761
user14751761

Reputation:

Reactjs useState hook not updating on promise data

I am using react hook instead of class based component but it is not updating the state when i fetch data from graphql API.

Here you go for my code:

import React, { useEffect, useState } from 'react';
import client from '../gqlClient';
import { gql, ApolloClient, InMemoryCache  } from '@apollo/client';


const client = new ApolloClient({
  uri: 'http://localhost:8000/graphql/',
  cache: new InMemoryCache(),
});


function EmpTable() {

  const [employee, setEmployee] = useState({});

    useEffect(() => {

        client
            .query({
                query: gql`
                query {
                  employees {
                    name
                  }
                }
                `
            })
            .then(result => {
              setEmployee({result});
              console.log(employee);
            });
    }, [])

    return (
        <div>return something</div>
    )
};


export default EmpTable;

When i print the employee It prints the initial value only.

But when print result, the console showing all the data that i have from API.

I made the useEffect only run once the page/component is loaded but it is not working.

Can anyone help me how to fix the issue?

Upvotes: 0

Views: 1277

Answers (3)

Hamid Shoja
Hamid Shoja

Reputation: 4768

There is another solution that you can use a custom hook to use your returned value in any component you want to use.

import React, { useEffect, useState } from 'react';
import client from '../gqlClient';
import { gql, ApolloClient, InMemoryCache  } from '@apollo/client';


const client = new ApolloClient({
  uri: 'http://localhost:8000/graphql/',
  cache: new InMemoryCache(),
});

const useCustomApi=()=>{
    const [employee, setEmployee] = useState({});
    useEffect(() => {
        client
            .query({
                query: gql`
                query {
                  employees {
                    name
                  }
                }
                `
            })
            .then(result => {
              setEmployee({result});
              
            });
    }, [])


return employee;
}

function EmpTable() {

    const employee = useCustomApi();
    console.log(employee);

   return (
      <div>{JSON.stringify(employee,null,2)}</div>
   )
};


export default EmpTable;

Upvotes: 0

Hamid Shoja
Hamid Shoja

Reputation: 4768

You need to use useEffect hook to achieve this.

more information about How to use setState callback on react hooks How to use `setState` callback on react hooks

here is your code should be:

import React, { useEffect, useState } from 'react';
import client from '../gqlClient';
import { gql, ApolloClient, InMemoryCache  } from '@apollo/client';


const client = new ApolloClient({
  uri: 'http://localhost:8000/graphql/',
  cache: new InMemoryCache(),
});


function EmpTable() {

  const [employee, setEmployee] = useState({});

    useEffect(() => {
        client
            .query({
                query: gql`
                query {
                  employees {
                    name
                  }
                }
                `
            })
            .then(result => {
              setEmployee({result});
              
            });
    }, [])

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

   return (
      <div>{JSON.stringify(employee,null,2)}</div>
   )
};


export default EmpTable;

Upvotes: 0

wangdev87
wangdev87

Reputation: 8751

setEmployee is the asynchronous method so you can't get the updated value of employee immediately after setEmployee.

setEmployee({result});
console.log(employee); // This will show the old `employee` value.

You should get the updated result in the useEffect with adding a employee dependency.

useEffect(() => {
        client
            .query({
                query: gql`
                query {
                  employees {
                    name
                  }
                }
                `
            })
            .then(result => {
              setEmployee({result});
              console.log(employee);
            });
}, [])

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

Upvotes: 2

Related Questions