Koala7
Koala7

Reputation: 1404

React Conditional Rendering with states

I am working in a component where if i click on the NavItem i render an other list of elements

Function changing the state

handleClick() {
  this.setState({
    isActive: !this.state.isActive
  });
};

The Conditional Rendering

if (isActive) {
  SubList = <List hasIcons style="secondary"><ListItem><NavItem href={desktopUrl} title={title}><Icon name={name} />{title}</NavItem></ListItem></List>
}

The List NavItem and the {{SubList}}

<ListItem>
    <NavItem isActive href={desktopUrl} title={title} onClick={this.handleClick}>
        <Icon name={name} />
        {title}
    </NavItem>
    {SubList}
</ListItem>

Here the whole component

export default class SportNavItem extends React.Component {
  constructor() {
    super();
    this.state = { isActive: false };
    // This binding is necessary to make `this` work in the callback
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    this.setState({
      isActive: !this.state.isActive
    });
  }

  render() {
    const { title, desktopUrl, isActive, name } = this.props.data;
    // props.childItems; { title, name, isActive, url }

    // const itemId = `nav-${slugEn}`;
    const style = isActive ? "primary" : "default";

    let SubList = null;

    if (isActive) {
      SubList = (
        <List hasIcons style="secondary">
          <ListItem>
            <NavItem isActive href={desktopUrl} title={title}>
              <Icon name={name} />
              {title}
            </NavItem>
          </ListItem>
        </List>
      );
    }

    return (
      <List hasIcons style={style}>
        <ListItem>
          <NavItem isActive href={desktopUrl} title={title} onClick={this.handleClick}>
            <Icon name={name} />
            {title}
          </NavItem>
          {SubList}
        </ListItem>
      </List>
    );
  }
}

The Component exported

const sampleData = {
  title: 'Football',
  name: 'football',
  isActive: true,
  desktopUrl: '#'
}

ReactDOM.render(
    <div>
        <SportNavItem data = { sampleData }/>
    </div>,
    document.getElementById('app')
);

If i manually change the status isActive to false i can render the SubList. I can not achieve to handle the status onClick and i do not see error in the console. What is possibly wrong? Is there a better way?

Upvotes: 2

Views: 2379

Answers (3)

Diego Faria
Diego Faria

Reputation: 9185

You cannot onClick on custom component. Wrap NavItem with a div that has the onClick method.

Upvotes: 0

Shubham Khatri
Shubham Khatri

Reputation: 281626

Firstly as @Jacob suggested, your variable isActive is a state and not a prop. You should use it like

const { title, desktopUrl, name  } = this.props.data;
const {isActive} = this.state;

Secondly, If NavItem is a custom component created by you then onClick={this.handleClick} will not set an onClick event on the NavItem rather than pass onClick as a prop to the NavItem component. In the NavItem component you can have an onClick event on a div that will in turn call the onClick function from the props resulting in this.handleClick being called. If you look at the NavItem component in ReactBootstrap. It has an onClick prop which will basically be doing the same thing as I suggested above

So technically you cannot have an onClick event on to any component. You can wrap the NavItem inside a div and then set an onClick event on that div

     <ListItem>
         <div onClick={this.handleClick}>   
            <NavItem isActive href={desktopUrl} title={title} >
                <Icon name={name} />
                {title}
            </NavItem>
            {SubList}
         </div>
    </ListItem>

Upvotes: 0

Jacob
Jacob

Reputation: 78850

You are trying to read isActive from this.props.data:

const { title, desktopUrl, isActive,  name  } = this.props.data;

...but isActive is in this.state. Change to this instead:

const { title, desktopUrl, name } = this.props.data;
const { isActive } = this.state;

Upvotes: 1

Related Questions