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} />
      </>
    );
  }
}
cdt
  • 193
  • 1
  • 2
  • 17
  • 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 : ...` – Heretic Monkey Feb 24 '21 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} – LucasSousa Feb 24 '21 at 17:19
  • If you use [optional chaining](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/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. – David784 Feb 24 '21 at 17:21

3 Answers3

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
Oli
  • 852
  • 6
  • 12
  • If you really want null rather than (possibly) undefined, use [nullish coalescing operator `??`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator) rather than OR. – Heretic Monkey Feb 24 '21 at 17:26
  • 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 – Oli Feb 24 '21 at 17:35
  • the first example worked perfectly! – cdt Feb 24 '21 at 18:06
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].

Christian Fritz
  • 20,641
  • 3
  • 42
  • 71
0

try to check out the type:

 {  typeof story.multipedia[0].url === "undefined"
     ? img_default
     : story.multimedia[0].url
 }
alexrogo
  • 522
  • 3
  • 17
  • This will still throw the same error, assuming `story.multipedia[0]` == `null` – Oli Feb 24 '21 at 17:31
  • assuming `story.multipedia[0] === null` is possible, you could also check it with `if (story.multipedia[0])` – alexrogo Feb 24 '21 at 17:34