1

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>
);

};

3 Answers 3

5

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])
Sign up to request clarification or add additional context in comments.

Comments

0

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.

1 Comment

Nice catch on the log outside of .then(). Just wanted to note that, if you log searchResults like this, it will log on every re-render, even if searchResults doesn't change.
0

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>
);
};

5 Comments

How is this different than my answer? And spread operator is not needed in this example.
No different than yours except spread operator. My concewrn was that if he is a beginner one then he will get whole set of edited code.
The spread operator does nothing here, certainly doesn't optimize the code. It is essential if the current state is used, like setSearchResults(r => [...r, ...res.data.Search])
I have seen that in many cases jsx dosen't re renders if a coder just replaces whole array in setState with new one instead of manipulating it, but was solved by spreading the result array into setState... may be i am wrong
It happens when the state variable is mutated directly, without creating a copy. If you set a whole different array to the state variable, you don't need to create a copy of it by spreading.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.