0

I have a project in React and Typescript and am creating a Like button and created an if/else statement as so:

  const [count, setCount] = useState(0);
  const [iconFill, setFill] = useState('gray');

  const favoriteCount = () => {
    if(iconFill == 'red') {
      setCount(count - 1 );
      setFill('gray');
    } 
    else {
      setCount(count + 1);
      setFill('red');
    }
  }

The code works as expected but I am wondering if there is a more concise way to write it, I tried using a ternary statement:

iconFill == 'red' ? setCount(count - 1 ) && setFill('gray') : setCount(count + 1) && setFill('red');

I am unsure of why this doesn't produce the same result and am also getting the following Typescript error: An expression of type 'void' cannot be tested for truthiness

3
  • 7
    Why would this ... ? ... : ... be any better? Write code that you can understand by only looking at it. Anything else is the job of a specialized tool. Commented Sep 29, 2020 at 13:59
  • Typescript says that void type cannot be casted to boolean. State modifiers returns void type. Commented Sep 29, 2020 at 13:59
  • favoriteCount() is a void function. You should use ternary operator incase you need something in return. Commented Sep 29, 2020 at 14:15

4 Answers 4

3

I think your original existing code is fine - using the conditional operator not only makes it a lot harder to read, but it also just isn't appropriate because the conditional operator is meant to be used when you want to conditionally produce an expression (but the resulting expression here isn't being used). if/else is more appropriate.

But there is an alternative that can make your code more concise. Because it looks like iconFill toggles between gray and red, how about making that state a boolean instead of a string? Then you can just invert the boolean:

const [fillGray, setFillGray] = useState(true);
const favoriteCount = () => {
    setCount(count + (fillGray ? 1 : -1));
    setFillGray(!fillGray);
}

The conditional operator is used above, but it's in a more appropriate context because the result is used as an expression (that is, to evaluate to 1 or -1) rather than as an inappropriate replacement for if/else.

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

1 Comment

thanks for explanation and the suggestion for the boolean, it makes sense and make the code more concise :)
1

Another approach can be:

    setCount(iconFill === "red" ? count - 1 : count + 1);
    setFill(iconFill === "red" ? "gray" : "red");

Here the limitation is checking for condition twice.

Comments

1

Should you change your code? No, moving to ternary here is not an improvement, so I wouldn't.

Why doesn't your proposed code work? In your proposed code setCount(count - 1 ) && setFill('gray'), the setFill command will only execute if setCount returns truthy. In all likelihood, your setter methods return undefined, so the code after && will never execute. There is no point in evaluating B in A && B if A is false. The evaluation is short-circuited.

Also, minor comment, prefer === over == in JavaScript.

Comments

0

Thanks for responses everyone, makes sense to me now why ternary would not be appropriate for this scenario, keeping my original!

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.