Why am I getting first response as an empty array in react?

Viewed 767

Below I am trying to fetch data and use the onInputValue function in my other component called Search. It's working fine after first attempt, but I am getting an empty array in my initial button click


const App = () => {
    const [results, setResults] = useState([]);


    const onInputValue = async (input) => {
        
        const { data } = await nasa.get('/search', {
            params: {
                q: input,
            },
        });
        if(!results) {
            return;
        }
        setResults(data.collection.items);
        console.log(results);
    };
    return (
        <div>
            <Search onInputValue={onInputValue} />
        </div>
    );
};


import React, { useState} from 'react';

const Search = ({ onInputValue }) => {
    const [input, setInput] = useState('');

    return (
        <div className='input-group mb-3'>
            <input
                type='text'
                className='form-control'
                placeholder='To infinity and beyond!'
                onChange={(e) => setInput(e.target.value)}
            />
            <div className='input-group-append'>
                <button
                    onClick={() => {onInputValue(input)}}
                    className='btn btn-outline-secondary'
                    type='button'
                >
                    <i className='fas fa-rocket'></i>
                </button>
            </div>
        </div>
    );
};

export default Search;

Below is the result I get. enter image description here

Please advise

3 Answers

setResults is asynchronous if you want to check results you can use useEffect

const App = () => {
  const [results, setResults] = useState([]);

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

  const onInputValue = async (input) => {
    const {data} = await nasa.get('/search', {
      params: {
        q: input,
      },
    });
    if (!results) {
      return;
    }
    setResults(data.collection.items);
  };
  return (
    <div>
      <Search onInputValue={onInputValue} />
    </div>
  );
};

This is due to asynchronous nature of setResults function - after calling it, the updated value of results will be available on the next component render - in your example you're logging in to console immediately after invoking setResults.

It could be because the setResults is batched and therefore move to the next line.

See useState batch updates.

Also

if(!results) { return; }

Is a bit suspect. ![] === false and !['someValue'] === false

Related