2

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
  • 1
    The problem is story.multimedia is null. The error is thrown on the condition of the ternary, so you need to check for null in the condition, either with story.multimedia ? story.multimedia[0].url : ... or, if you're targeting modern browsers, optional chaining; story.multimedia?.[0]?.url ? story.multimedia[0].url : ... Commented Feb 24, 2021 at 17:19
  • I do not know if this can help, but if you try something like this: img={!story.multimedia[0].url ? null : story.multimedia[0].url} Commented Feb 24, 2021 at 17:19
  • If you use optional chaining you probably don't really even need a ternary img={story?.multimedia?.[0]?.url} And since this is JSX, babel will be transpiling it anyway, so no worries about browser support most likely. Commented Feb 24, 2021 at 17:21

3 Answers 3

2

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

3 Comments

If you really want null rather than (possibly) undefined, use nullish coalescing operator ?? rather than OR.
It's a good point @HereticMonkey. || checks for a falsy value. Probably you still want to use || here, because it's unlikely you'd want a url as 0 or "", for example
the first example worked perfectly!
0

try to check out the type:

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

2 Comments

This will still throw the same error, assuming story.multipedia[0] == null
assuming story.multipedia[0] === null is possible, you could also check it with if (story.multipedia[0])
0

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].

2 Comments

Syntax for array optional chaining is ?.[0], (with a dot)
And it's covered in the duplicate...

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.