How to avoid nested ternary operators

Viewed 788

Here is my code which is repeating pretty often, and I would like to avoid this:

{ isDataLoading ? (
            <MyLoadingComponent />
            ) : !products ? (
            <ThereIsNoDataComponent />
        ) : ( <div>Some text</div> )
    }

How could I write this to avoid nested ternary operators?

Thanks guys

Cheers

4 Answers

You could wrap the logic in a function and call it from your jsx block

const render = () =>{
    if(isDataLoading) return <MyLoadingComponent />
    if(!products) return  <ThereIsNoDataComponent />
    return <div>Some text</div>
}

return render()

This case seems like a pattern that could happen more than once in application, so it might be worth implementing another component for handling this logic, e.g.

<Loader isLoading={isDataLoading} hasData={!!products} >
   <Products product={products} />
</Loader>

Loader component would render child components only if there is data and it is not loading, it would show placeholder message otherwise.

There is an example https://codepen.io/wilski-micha/pen/bGGbewm

One option is to make an IIFE:

{
(() => {
  if (isDataLoading) return (<MyLoadingComponent />);
  if (!products) return (<ThereIsNoDataComponent />);
  return (<div>Some text</div>);
})()
}

Or, if you want to avoid re-creating the function every time:

const render = (isDataLoading, products) => {
  if (isDataLoading) return (<MyLoadingComponent />);
  if (!products) return (<ThereIsNoDataComponent />);
  return (<div>Some text</div>);
};

and

{ render(isDataLoading, products) }

I am using this custom helper:

const switchTrue = (object) => {
  const { default: defaultValue, ...rest } = object;
  const obj = { default: defaultValue, ...rest };
  const result = Object.keys(obj).reduce((acc, cur) => {
    return {
      ...acc,
      [cur === 'default' ? 'true' : cur]: obj[cur],
    };
  }, {});
  return result['true'];
};

const isDataLoading = false;
const products = false;
const component = switchTrue({
  [`${Boolean(isDataLoading)}`]: '<MyLoadingComponent />',
  [`${!products}`]: '<ThereIsNoDataComponent />',
  default: '<div>Some text</div>',
});

console.log(component) // <ThereIsNoDataComponent />

Related