React: Conditional Render - "Cannot read property '0' of null"

Viewed 900

Highlight of my problem. I'm trying to add conditional rendering to the image prop. Some "Stories" I pull from the API don't have images so I need to account for that so I don't get the "TypeError: Cannot read property '0' of null" error, but this still isn't working when I add the ternary operator.

<Story
  key={idx}
  title={story.title}
  abstract={story.abstract}
  img={story.multimedia[0].url ? story.multimedia[0].url : null} // why doesn't this work?
  alt={story.multimedia[0].caption ? story.multimedia[0].caption : null} // why doesn't this work?
  link={story.url}
/>;

Can I add a fallback link to a "placeholder" image URL?

  img={story.multimedia[0].url ? story.multimedia[0].url : "https://www.example.com/example.png"}

Full component here

export default function News() {
  const [error, setError] = useState(null);
  const [stories, setStory] = useState(null);

  useEffect(() => {
    const getCurrentPage = () => {
      const url = new URL(window.location.href);
      const page = url.pathname.split("/").pop();
      return page ? page : "home";
    };
    const section = getCurrentPage();
    fetch(
      `https://api.nytimes.com/svc/topstories/v2/${section}.json?api-key=4fzCTy6buRI5xtOkZzqo4FfEkzUVAJdr`
    )
      .then((res) => res.json())
      .then((data) => {
        setTimeout(() => setStory(data), 1500);
        console.log("Success ", data);
      })
      .catch((error) => {
        console.log("Error", error);
        setError(error);
      });
  }, []);

  if (error) {
    return <div>Error: {error.message}</div>;
  } else if (!stories) {
    return <LoadingBar type={"cylon"} color={"#193152"} />;
  } else {
    return (
      <>
        <ul className="stories">
          {stories.results.map((story, idx) => {
            return (
              <Story
                key={idx}
                title={story.title}
                abstract={story.abstract}
                img={story.multimedia[0].url ? story.multimedia[0].url : null} // why doesn't this work
                alt={ story.multimedia[0].caption ? story.multimedia[0].caption : null } // why doesn't this work?
                link={story.url}
              />
            );
          })}
        </ul>
        <Spacer height={100} />
      </>
    );
  }
}
3 Answers

Cannot read property '0' of null" suggests that story.multimedia is null, and this is not being checked.

You should probably extend your checks like so:

story && story.multimedia && story.multimedia[0] && story.multimedia[0].url ? story.multimedia[0].url : null

story && story.multimedia && story.multimedia[0] && story.multimedia[0].caption ? story.multimedia[0].caption : null

Or if you want to use optional chaining (if your environment supports it):

story?.multimedia?.[0]?.url || null

story?.multimedia?.[0]?.caption || null

Looks like story.multimedia can be null. Either use story.multimedia?.[0] if this is supported in your environment (e.g., via babel) or go old-school and use story.multimedia && story.multimedia[0].

try to check out the type:

 {  typeof story.multipedia[0].url === "undefined"
     ? img_default
     : story.multimedia[0].url
 }
Related