Why is this JSX code (UI Kit) wrong?

I have a UI Kit render where editor and linter complain about the syntax, but not if I do the same one level simpler.

The code is based on an array (renderSource). If empty, neither form nor table generated from the array should be rendered. But if the array is not empty, but the ‘depth’ to show is 0, the form should be shown so that the user can increase depth to show what is hidden otherwise.

This isn’t correct:

    <Heading size="large">Design Library Info</Heading>
    {(renderSource.length > 0 ? 
      <Form onSubmit={onSubmit}><TextField label="Show depth" name="depth" type="number" defaultValue={formState.depth}/></Form>
      {(`${formState.depth}` !== "0" ?
      <Table>
        <Head><Cell><Text>This design depends on</Text></Cell><Cell><Text>Inherited requirements</Text></Cell></Head>
          {renderSource.map(depEntry => {
              return (
                <Row>
                  <Cell><Text><Link href={`${depEntry.link}`}>{depEntry.title}</Link></Text></Cell>
                  <Cell><Text>{depEntry.req}</Text></Cell>
                </Row>
              )
            })
          }
      </Table>:<Text>(Increase depth to show dependencies)</Text>)}
    :<Text>(This design does not have dependencies)</Text>)}

But this, with only one conditional, works: If depth is set to 0 in the form, the form is shown, but the table isn’t:

    <Heading size="large">Design Library Info</Heading>
      <Form onSubmit={onSubmit}><TextField label="Show depth" name="depth" type="number" defaultValue={formState.depth}/></Form>
      {(`${formState.depth}` !== "0" ?
      <Table>
        <Head><Cell><Text>This design depends on</Text></Cell><Cell><Text>Inherited requirements</Text></Cell></Head>
          {renderSource.map(depEntry => {
              return (
                <Row>
                  <Cell><Text><Link href={`${depEntry.link}`}>{depEntry.title}</Link></Text></Cell>
                  <Cell><Text>{depEntry.req}</Text></Cell>
                </Row>
              )
            })
          }
      </Table>:<Text>(Increase depth to show dependencies)</Text>)}

What is wrong with my syntax here?

Below code fixes your first example. I found two problems. First, React expects a single top level element to be returned so I wrapped everything in a <Fragment>. Second, that rule also applies to expressions and functions that return jsx elements. Your outermost unary expression (renderSource.length > 0 ?) is returning several top level elements so you needed to wrap those in a Fragment as well

<Fragment><Heading size="large">Design Library Info</Heading>
    {(renderSource.length > 0 ? 
      <Fragment><Form onSubmit={onSubmit}><TextField label="Show depth" name="depth" type="number" defaultValue={formState.depth}/></Form>
      {(`${formState.depth}` !== "0" ?
      <Table>
        <Head><Cell><Text>This design depends on</Text></Cell><Cell><Text>Inherited requirements</Text></Cell></Head>
          {renderSource.map(depEntry => {
              return (
                <Row>
                  <Cell><Text><Link href={`${depEntry.link}`}>{depEntry.title}</Link></Text></Cell>
                  <Cell><Text>{depEntry.req}</Text></Cell>
                </Row>
              )
            })
          }
      </Table>:<Text>(Increase depth to show dependencies)</Text>)}</Fragment>
    :<Text>(This design does not have dependencies)</Text>)}</Fragment>
1 Like

I see, thank you. I actually did have a <Fragment> around the entire code that the render function returned. It was the inner Fragment that is needed to create a single entity for the conditional element that consists of both a Form and a Table. I was under the assumption that having that outer Fragment I had covered the ‘single item’ requirement.

Summary

This text will be hidden