-1

I'm trying to use a <Conditional if={condition}> component in React, that renders its content only if the condition is true.

I've used the code from here, as mentioned in Broda Noel's response of this question. You also see the code here.

import * as React from 'react';

const Conditional = props => (
    !!props.if && props.children
);

class Item extends React.Component {
    render() {
        const item = { id: 2 };

        return (
            <>
                <h2>Item detail</h2>
                {/* Display item.foo.name if `foo` property exists */}
                <Conditional if={item.foo}>
                    {item.foo.name}
                </Conditional>
            </>);
    }
}

export default Item;

It fails with the error:

Uncaught TypeError: Cannot read property 'name' of undefined

I know I can also use {item.foo && item.foo.name}, but when the code becomes more complex, I find the use of Conditional more readable. And most important, I would really like to understand what happens here.

Why does React render the content of the Conditional, even is the condition is false? Is there a way to change the Conditional component to make it work in this case?

I'm using React 16.4.1, with typescript.

obourgain
  • 8,856
  • 6
  • 42
  • 57
  • Try to set the if to `if={item.foo !== undefined} `. Your if have no condition, comparison or anything like. – reisdev Dec 02 '18 at 18:00

2 Answers2

2

The code:

<Conditional if={item.foo}>
  {item.foo.name}
</Conditional>

is transpiled to:

React.createElement(Condition, { if: item.foo }, item.foo.name)

So even if the condition is false it will try to access the property name.

I suggest that you use the code below when the code becomes more complex:

import * as React from 'react';

class Item extends React.Component {
  renderConditional (item) {
    if (!item.foo) {
      return null;
    }
    return item.foo.name; // Or some jsx
  }

  render() {
    const item = { id: 2 };

    return (
      <>
        <h2>Item detail</h2>
        {this.renderConditional(item)}
      </>
    );
  }
}

export default Item;

You could also create another component to present the data and check the object inside the new component.

kakamg0
  • 1,096
  • 5
  • 12
1

The problem is that your component <Conditional> have no logical expression in the if prop. The "React way" to do this is using conditional rendering as is:

render() {
    const item = { id: 2 };

    return (
      <>
        <h2>Item detail</h2>
        { item.foo !== undefined &&  // React Way to Conditional Rendering
          {item.foo.name}
        }
      </>
    );
}

I recommend you to read the docs for Conditional Rendering

reisdev
  • 3,215
  • 2
  • 17
  • 38