1

I'm new to React and TypeScript. I cannot find a solution for this on Google.

I have a component that outputs an image. I want to wrap that image in an <a> tag if there is a given URL prop. I am unsure how to write the logic simply enough.

From looking online I have written the following:

const imageBlock = ({
  imageSrc,
  imageAlt,
  imageTitle,
  imageLink,
}: imageBlockProps) => {
  return (
    imageLink && (
      <a href={imageLink}>
    )
      <img src={imageSrc} alt={imageAlt} title={imageTitle} />

    imageLink && (
      </a>
    )
  )
};

But I cannot get it to work.

Would anyone know the best way to do it?

2
  • 1
    You cannot do it in a single expression without extra assignment or duplicating <img> Commented May 13, 2020 at 6:43
  • @zerkms ok cool, but I'm still not sure how it's meant to go Commented May 13, 2020 at 6:49

3 Answers 3

6

There is nothing wrong in writing imperative code, really:

const img = <img src={imageSrc} alt={imageAlt} title={imageTitle} />;

if (imageLink) {
    return <a href={imageLink}>{img}</a>;
}

return img;
Sign up to request clarification or add additional context in comments.

5 Comments

ternary way: return imageLink ? <a href="..">{img}</a> : img;
@mickdev it does not add anything to the original code though :shrug: (other than making it harder to read)
I know, it's because the author was asking for ternary way to do it ^^
@mickdev I thought the OP wanted a single-expression way of doing it :shrug: But anyway, sorry :-)
@zerkms it's harder to read only if it's not formatted properly
0

As @zerkms said, there's nothing wrong with an if statement.

But... what you could do is something like this:

const ConditionalLinkWrapper = ({ link, wrapper, children }) => 
  link ? wrapper(children) : children;

Your code then would use this reusable component like this:

const imageBlock = ({
  imageSrc,
  imageAlt,
  imageTitle,
  imageLink,
}: imageBlockProps) => (
  <ConditionalLinkWrapper
    link={imageLink}
    wrapper={children => <a href={imageLink}>{children}</a>}
  >
    <img src={imageSrc} alt={imageAlt} title={imageTitle} />
  </ConditionalLinkWrapper>
);

In my opinion, it's cleaner and easier to read than with an if statement, but that might not be the case for everyone!

I also like the fact that this is following the Composition vs Inheritance pattern.

You can also reuse the ConditionalLinkWrapper component anywhere in your code if you need to.

2 Comments

"it's cleaner and easier to read" --- and it also is broken. Now curious how long it will take to find it in such a messy (subjective, I know) code. Now take a timer and honestly report it, without running it somewhere :-)
@zerkms: Not sure if that was the wrongly named prop but if that was the only issue (didn't see anything else tbh)... I don't really get the comment then :) Also, my mistake could be easily avoided with TS (also, not writing code directly inside SO editor could help). As I said, I find this pattern quite clear and useful to not write if statements over and over again in the entire codebase, but that's only my opinion :)
0

This is not recommended, but if you're really looking for a one-liner, check this out:

return ((img = <img src={imageSrc} alt={imageAlt} title={imageTitle} />) => 
  imageLink
    ? <a href={imageLink}>{img}</a>
    : img
)()

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.