m4tt
m4tt

Reputation: 955

complex tertiary if else statement (jsx)

Dealt with jsx statement before, so I was pretty confident this worked fine but it seems the skeleton block at the end is shown on mobile as well which is not as intended

      {!isMobile && 
          !session ?
            <NormalComponent />
          : data ?
            <UserComponent />
            : <div className="d-flex flex-column">
                <Skeleton width={150} height={28} />
                <br /><br />
                <Skeleton circle={true} height={65} width={65} className="mr-2" />
              </div>
       }

the above tries to be the equivalent of:

if (!isMobile) {
   if (!session) {
      <NormalComponent />
   }else{
      if (data) {
          <UserComponent />
      }else{
          // show skeleton stuff while it loads data
      }
   }
}

Upvotes: 0

Views: 340

Answers (1)

Ori Drori
Ori Drori

Reputation: 192507

The statement !isMobile && !session is considered a single boolean expression, and it effects the 1st ternary. In your case if isMobile it true, you don't want to render anything.

Wrap the !session ternary with parentheses:

const NormalComponent = () => <div>NormalComponent</div>
const UserComponent = () => <div>UserComponent</div>
const Skeleton = (props) => <div {...props}>Skeleton</div>

const Demo = ({ isMobile, session, data }) => (     
  !isMobile && (
    !session ?
      <NormalComponent />
    : data ?
      <UserComponent />
      : <div className="d-flex flex-column">
          <Skeleton width={150} height={28} />
        </div>
  )
)

ReactDOM.render(
  <React.Fragment>
    isMobile is falsy - renders skeleton:
    <Demo session />
    <br />
    isMobile true - render nothing:
    <Demo isMobile session />
  </React.Fragment>,
  root
)
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>

<div id="root"></div>

A more readable solution would be to use if, and return as soon as a condition is met:

const NormalComponent = () => <div>NormalComponent</div>
const UserComponent = () => <div>UserComponent</div>
const Skeleton = (props) => <div {...props}>Skeleton</div>

const Demo = ({ isMobile, session, data }) => {
  if(isMobile) return null;
  
  if(!session) return <NormalComponent />;
  
  return data ?
    <UserComponent />
    : (
      <div className="d-flex flex-column">
        <Skeleton width={150} height={28} />
      </div>
    );
};

ReactDOM.render(
  <React.Fragment>
    isMobile is falsy - renders skeleton:
    <Demo session />
    <br />
    isMobile true - render nothing:
    <Demo isMobile session />
  </React.Fragment>,
  root
)
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>

<div id="root"></div>

Upvotes: 1

Related Questions