0

I'm pulling stuff from my database using Firestore. When I log inside the function that pulls the data, the array has the data. When I log in my main component, it also has. But for some reason, .map doesn't work, and when I try array.length it returns 0. I was using a map, but then I changed it to use a function to try to get the error.

export default function Search() {
  const [searchedData, setSearchedData] = useState([]);
  const [loading, setLoading] = useState(true);
  const [noBook, setNoBook] = useState(false);
  const [showBooks, setShowBooks] = useState(false);

  const link = useLocation();
  useEffect(() => {
    const srch = link.pathname.substring(8);
    loadSearchBooks(srch);
  }, [link]);

  async function loadSearchBooks(srch) {
    try {
      const bookArray = await getSearchedBooks(srch);
      bookArray ? setShowBooks(true) : setNoBook(true);
      setSearchedData(bookArray);
    } catch (e) {
      setSearchedData(null);
    } finally {
      setLoading(false);
    }
  }

  function renderBooks() {
    console.log(searchedData);
    const l = searchedData.length;
    return l;
  }

  return (
    <div>
      <Navbar />
      <div className={searchBookWrapper}>
        {loading && 'Carregando'}
        {showBooks && renderBooks()}
        {noBook && <BookCardItem />}
      </div>
    </div>
  );
}

When doing this, console.log(searchedData) returns the array, but const l = searchedData.length shows just a 0. When I search again, the number changes to 12 for a moment right when it's about to change. This is the previous code:

  return (
    <div>
      <Navbar />
      <div className={searchBookWrapper}>
        {loading && 'Carregando'}
        {showBooks &&
          searchedData.map(({ afn, aln, notes, quant, title }, index) => {
            return (
              <BookCardItem
                key={title}
                firstName={afn}
                lastName={aln}
                notes={notes}
                quant={quant}
                title={title}
                bookNumber={index}
              />
            );
          })}
        {noBook && <BookCardItem />}
      </div>
    </div>
  );
}

The same thing happened. The bookInfo appeared just for a moment when I searched again.

From the first code in this question, this is the console:

Console - one empty array, then two filled ones

Dione
  • 43
  • 3
  • 1
    Please post `getSearchedBooks`. I bet it's returning an empty array (that react renders) before filling it asynchronously. This also corresponds exactly to [what your log shows](https://stackoverflow.com/q/4057440/1048572). – Bergi Mar 01 '22 at 22:05

1 Answers1

-1

if useLocation is an API call or other async function, react prefers those to be in a useEffect. If they are not, it can give inconsistent results. Try putting useLocation inside a useEffect. If you only plan on useLocation firing once (and thus loadSearchedBooks only firing once) you can even put them in the same useEffect, just don't make them rerender based on the thing they update.

useEffect(() => {
  useLocation().then(link => {
  const srch = link.pathname.substring(8);
  loadSearchBooks(srch);
    }
  }, []);

Hopefully, this will fix your problem.

  • `useLocation` clearly (judging by its name) is a hook, and must not be called from an effect. – Bergi Mar 01 '22 at 22:07