1
const ModalButton = ({ label, mode }) => {
  return (
    <button type="submit">
      {mode == "new" && (
        <FaPlusCircle style={{ fontSize: "20px", paddingTop: "6px" }} />) label
      }
    </button>
  );
};

This label is underlined as red in my code editor. Why it won't let me to have JavaScript with JSX?

Mishen Thakshana
  • 1,050
  • 1
  • 14
  • 38
  • 2
    This is invalid syntax, what are you trying to do? – Konrad Sep 06 '22 at 10:19
  • What does `label` contains? – 0stone0 Sep 06 '22 at 10:20
  • I'm trying to conditional render an icon if mode is new render this else another one. Label is a prop (string value) I want to have it next to the icon – Mishen Thakshana Sep 06 '22 at 10:21
  • At least related: https://stackoverflow.com/questions/69011851/how-to-append-a-string-and-html-tag-in-ternary-operator-condition, https://stackoverflow.com/questions/48886726/why-do-i-get-the-error-expressions-must-have-one-parent-element-how-do-i-fix – T.J. Crowder Sep 06 '22 at 10:25

3 Answers3

3

The second operand of && has to be a single value; right now, you're trying to give it two. To treat the icon and the text node after it as a unit (a single value), you need to wrap them in something, such as a fragment: <>_____</>

const ModalButton = ({ label, mode }) => {
    return (
        <button type="submit">
            {mode == "new" && (
                <>
                    <FaPlusCircle style={{ fontSize: "20px", paddingTop: "6px" }} />
                    {label}
                </>
            )}
        </button>
    );
};

(You also had the ) in the wrong place; I've fixed it above. It shouldn't be just after the icon, it should be after the entire operand for && [so with this change, it's after the end of the fragment].)

Also, if you want to use the value of label, you'll need to wrap it in a JSX expression (as above): {label}.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
2

As rightly commented by @Konrad Linkowski

This is invalid syntax

What is the issue with it?

What you are using is called expression. So condition1 && condition2 will return false if condition1 is falsey or will return condition2.

In your expression, its condition1 && condition2 condition3. There needs to be an operator between condition2 and condition3 or they need correct structure.


If you want label to always render and icon for "new" buttons, it should be:

{condition1 && condition2}
{condition3}

but if you need them to render together or none, you need to wrap then so that your expression returns 1 value:

{
    condition1 &&
    (<>
        element1
        element2
    </>)
}


Sample

const ModalButton1 = ({ label, mode }) => {
  return (
    <button type="submit">
      {
        mode == "new" && (
        <FaPlusCircle style={{ fontSize: "20px", paddingTop: "6px" }} />)
      }
      { label }
    </button>
  );
};


const ModalButton2 = ({ label, mode }) => {
  return (
    <button type="submit">
      {
        mode == "new" && (
          <>
            <FaPlusCircle style={{ fontSize: "20px", paddingTop: "6px" }} />)
            {label}
          </>
      }
    </button>
  );
};
Rajesh
  • 24,354
  • 5
  • 48
  • 79
0

A JSX expression can only return a single value. If you want to return several values, wrap them in an array, like so:

{mode == "new" && [<Component/>, label]}
Good guy
  • 34
  • 1
  • 3
  • I think you might be being downvoted because "A JSX expression can only return a single element" is slightly misleading, it can only return a single value, but as you have shown, that value can contain multiple elements (in the case of arrays/nested JSX elements) Might be worth clarifying. – DBS Sep 06 '22 at 10:26
  • Or possibly having a component with no `key` in an array (but if it were me, I'd just comment that, not downvote). – T.J. Crowder Sep 06 '22 at 10:27
  • @DBS you're right, edited my answer. – Good guy Sep 06 '22 at 10:37