Caio Ishikawa
Caio Ishikawa

Reputation: 199

Cannot set React state to array of objects

I am trying to set a React state to an array of objects via an Axios get request. However, when I try to update the state, it shows up as an empty array.

I know for a fact that I am receiving the correct response from the API, so I think I am missing somethig when it comes to updating the state.

Here's my code:

const Home = () => {
const [movieTitle, setMovieTitle] = useState('');
const [searchResults, setSearchResults] = useState([]);

const handleChange = (e) => {
    setMovieTitle(e.target.value);
};

const getMovieData = () => {
    const apiKey = 'didntleakit';
    const apiUrl  = 'http://www.omdbapi.com/?apikey=' + apiKey + '&s=' + movieTitle;
    Axios.get(apiUrl)
        .then((res) => {
            setSearchResults(res.data.Search);
        });
    console.log(searchResults);
};

return(
    <div>
      <p>Home page</p>
      <TextField defaultValue="Movie" onChange={(e) => handleChange(e)}/>
      <button onClick={getMovieData}/>
    </div>
);

};

Upvotes: 1

Views: 1538

Answers (3)

Ayush Singh
Ayush Singh

Reputation: 126

You can not log state just after setting it as it is async so log it in useEffect and pass state as dependency array.

Always try to use spread operator while setting state if it is object or array.

const Home = () => {
const [movieTitle, setMovieTitle] = useState('');
const [searchResults, setSearchResults] = useState([]);

const handleChange = (e) => {
    setMovieTitle(e.target.value);
};

const getMovieData = () => {
    const apiKey = 'didntleakit';
    const apiUrl  = 'http://www.omdbapi.com/?apikey=' + apiKey + '&s=' + 
movieTitle;
    Axios.get(apiUrl)
        .then((res) => {
            setSearchResults([...res.data.Search]);//use spread operator for  optimised code
        });
    
};

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

return(
    <div>
      <p>Home page</p>
      <TextField defaultValue="Movie" onChange={(e) => handleChange(e)}/>
      <button onClick={getMovieData}/>
    </div>
);
};

Upvotes: 0

Shynggys Kengessov
Shynggys Kengessov

Reputation: 369

That's because you are logging searchResults BEFORE data was retrieved. Axios.get() is an async function, to fix it, just put console.log right before returning JSX code:

    console.log(searchResults);
    return (<div>....</div>);

So when the data is retrieved from the endpoint, you will update searchResults which will re-render the component with updated state and log correct searchResults to the console.

Upvotes: 0

Sinan Yaman
Sinan Yaman

Reputation: 5937

You cannot log the state variable right after setting it as setState is async. You can log the updated state inside a useEffect:

import {useEffect} from 'react'

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

Upvotes: 5

Related Questions