React UseEffect and UseState object undefined error

In my ClientData.js

I am using useEffect to call an API(which is working), then using useState to set the API response.data to a variable(which is working).

The response.data is an array of objects which I then set equal to a local variable. But when I attempt to access the object parameter I get a object undefined error.

I think the problem might be is that the object is undefined due to it waiting for the API response.

This is what the object from the API looks like:

objTest={
  ClientDatabase: "21",
  ClientID: "21",
  ClientName: "21",
  ClientServer: "21",
  Country: "US - 21",
  DatabaseVersion: "21",
  Namespace: "21",
};

function SimpleSelect() {
    const classes = useStyles();
    

    const [objTest, setobjTest] = useState([]);

    const clientAPI =  useCallback( async() => {
       
      //returns an array of objects
           await axios({
            method:'get',
             url,
            auth: {
                username: user,
                password: pass
            }
        })
        .then(function(response) {
  
         
            setobjTest(  response.data)
    
      
  
      
        })
        .catch(function (error){
            console.log(error);
        });

    })
    useEffect( () => {
        clientAPI();
        

        
    }, [])

When I attempt to access the object it works using console.log((objTest[0]));

but when I attempt to access the objects parameter like this: console.log((objTest[0].ClientDatabase));

it returns

TypeError: Cannot read property 'ClientDatabase' of undefined

This is the console log of response.data enter image description here

The response.data is an array.

Upvotes: 0

Views: 7973

Answers (3)

thealpha93
thealpha93

Reputation: 778

You put the initial state as an empty array. That's why you can't access it's first element. you can either set a non empty array as the initial state like this

const obj=[{
  ClientDatabase: "21",
  ClientID: "21",
  ClientName: "21",
  ClientServer: "21",
  Country: "US - 21",
  DatabaseVersion: "21",
  Namespace: "21",
}];

const [objTest, setobjTest] = useState(obj);

or you can check if the array is not empty

objTest.length && console.log(objTest[0].ClientDatabase)

The api call will take some time fetch the data. The initial state is what gives you the error

<Select labelId="demo-simple-select-label" id="demo-simple-select" value={age} onChange={handleChange} > {objTest.length && objTest.map(myList => { return( <MenuItem key = {myList.ClientDatabase} value = {myList} > {myList.ClientName} + {myList.Site} </MenuItem> ) })} </Select>

Try this out

Upvotes: 3

Ramesh Reddy
Ramesh Reddy

Reputation: 10652

The issue is with when you're logging the data. You're logging it a bit early.

So to check the modified state you can use an additional useEffect hook.

useEffect(() => {
  if(objTest.length > 0) {
    console.log(objTest[0].ClientDatabase)
  }
}, [objTest])

And when you want to use this in the JSX you can check if it's populated:

{
    clientArrTwo.length > 0 ? <Select labelId="demo-simple-select-label"
        id="demo-simple-select"
        value={age}
        onChange={handleChange} >
        {clientArrTwo.map(myList => {
            return (<MenuItem key={myList.ClientDatabase} value={myList} > {myList.ClientName} + {myList.Site} </MenuItem>)

        })}
    </Select> : null
}

Upvotes: 0

Pavlos Karalis
Pavlos Karalis

Reputation: 2966

Edit:

useEffect( () => console.log(objTest[0].ClientDatabase), [objTest])

Upvotes: 0

Related Questions