0

React is not rendering my mapped array after using asyn functions to call on API

I use the following useEffect to get characters into an array and set it as state in setRelatedCharacters

 // Find related characters
  useEffect(() => {
    // for promise to work in useEffect. need to put async function inside then call it
    const relatedCharacters = async () => {
      // if data exist. set related characters array by calling utility function and wait for it
      if (data) setRelatedCharacters(await relatedSwapi(data.characters));
    };
    relatedCharacters();
  }, [data]);

Then, when logging relatedCharacters, I get an array of 17 objects(characters).

Next, I send a condition to wait until the array is full of characters and when full I try to map through the array and render a name for each object in array. However, it quickly flickers and then disappears. I have no idea why.

{!data && !relatedCharacters ? (
        <Loading />
      ) : (
<div>

 <p>hello</p> // renders 
 {console.log(relatedCharacters, "<= relatedCharacters")} // shows correct array

 {relatedCharacters?.map((character) => (
                <p key={character.name}>{character.name}</p> //DOESN'T SHOW, SLIGHTLY FLICKERS ONLY
              ))}
</div>
)

-- EDIT FOR COMMENT -- Here is the entire code once taking away everything else

const Film = () => {
  const location = useLocation();
  const url = location.state.url;
  const index = location.state.index;
  const [data, setData] = useState(null);
  const [relatedCharacters, setRelatedCharacters] = useState(null);

  // Find related characters
// PROBLEM HAS TO BE HERE I THINK AS PROMISES AND SUCH ARE ACTING UP
const relatedSwapi = (data) => {
  let relatedArray = [];
  data.map(async (url) => {
    const related = await callSingleSwapi(url);
    relatedArray.push(related);
  });
  return relatedArray;
};

  useEffect(() => {
    const fetchCharacters = async () => {
      // if data exist. set related characters array by calling utility function and wait for it
      if (data) {
        const x = await relatedSwapi(data.characters);
        setRelatedCharacters(x);
      }
    };

    fetchCharacters();
  }, [data]);


  return (
   
          <div>
            <div className="relatedWrapper">
              <div className="flex space-x-3">
                {console.log(relatedCharacters, "<= related Characters")} // RENDERS AND THEN GOES BACK TO NULL
                {relatedCharacters?.map((character) => (
                  <p key={character.name}>{character.name}</p>
                ))}
              </div>
            </div>
      )}
    </div>
  );
};

export default Film;

Here is console.log(relatedCharacters) enter image description here

  • Why do you need relatedCharacters as an async function if you already have logic that conditionally renders relatedCharacters. – coot3 Apr 04 '22 at 01:43
  • Is there any other code calling `setRelatedCharacters`? Please post the complete code of the component, if possible as a [mcve]. – Bergi Apr 04 '22 at 01:57
  • relatedCharacters is just the state that is supposed to be an array. It shows an array for about 1 second then changes back to null. Also, no there is not another any other code calling setRelatedCharacters. – Hunter Scott Lacefield Apr 04 '22 at 02:20
  • `setData` is not called anywhere, so `relatedSwapi` is never called either? – Bergi Apr 04 '22 at 02:33
  • It is called. I just took those out trying to do minimal example – Hunter Scott Lacefield Apr 04 '22 at 02:35
  • 1
    Yes, there's a huge problem with your [asynchronous loop](https://stackoverflow.com/q/37576685/1048572) (you're pushing data into the array asynchronously, after having returned the empty array immediately - that also [explains the `console` output](https://stackoverflow.com/q/4057440/1048572) you're getting), that should be just `const relatedSwapi = (data) => Promise.all(data.map(callSingleSwapi));`. However, this doesn't really explain why your component would "flicker", unless there's something else that will cause it to re-render. – Bergi Apr 04 '22 at 02:35
  • I never heard of Promise.all. Sounds like that will do the trick once I do a little research on it – Hunter Scott Lacefield Apr 04 '22 at 02:38
  • Promise.all() did the trick! thank you for your help! – Hunter Scott Lacefield Apr 04 '22 at 02:46

0 Answers0