I'm using Material UI and React for a project, and I have a component, that roughly looks like this:

import React, { Component } from 'react';
import { List, ListItem } from 'material-ui';
import PropTypes from 'prop-types';

class MyComp extends Component {
    constructor(props) {
        super(props);

        this.onClickMethod = this.onClickMethod.bind(this);
    }

    onClickMethod() {
       // removed for brevity
    }

    render() {
        return (
            <div>
                <List>
                    {this.props.myData.map(pp => {
                        return (
                            <ListItem key={pp.name}
                                      style={styles.listItem}
                                      primaryText={pp.name}
                                      onClick={this.onClickMethod}
                            />
                        )
                    })}
                </List>
            </div>
        );
    }
}

const styles = {
    listItem: {
        // removed for brevity, includes some styles
    },
    listItemClicked: {
        // removed for brevity, includes different styles than the ones in listItem
    },
};

MyComp.propTypes = {
    myData: PropTypes.array.isRequired,
};

export default MyComp;

Now the point is that I want initially all my ListItems to have the same style, namely the styles inside the styles.listItem object property. Then, if the user clicks a certain ListItem I want its style to change to the styles that are inside the styles.listItemClicked object property. Though, the rest of the unclicked ListItems should not change their style. Additionally, if the user has already clicked a ListItem and decides to click another ListItem, then I want the previously clicked ListItem to change its style to the default one that is inside styles.listItem and the newly clicked ListItem to get the styles.listItemClicked styles. So that, at any time only zero (initially) or one of the ListItems have the styles inside the styles.listItemClicked. Any ideas how to achieve this in React?

2 Answers 11

up vote 2 down vote accepted

Maintain a state which contain the index of the listItem which was clicked and use a simple condition to change style of that particular item like this

class MyComp extends Component {
    constructor(props) {
        super(props);
        // Initialize a state which contain the index of clicked element (initially -1)
        this.state = { indexOfClickedItem: -1};
        this.onClickMethod = this.onClickMethod.bind(this);
    }

    onClickMethod(index) {
       // removed for brevity
       // When clicked then set the state with the index of clicked item
       this.setState({indexOfClickedItem: index});
    }

    render() {
        return (
            <div>
                <List>
                    {this.props.myData.map((pp,index) => {
                        return (
                            <ListItem key={pp.name}
                                      // Use simple condition to change the style of clicked element
                                      style={this.state.indexOfClickedItem === index ? styles.listItemClicked : styles.listItem}
                                      primaryText={pp.name}
                                      onClick={this.onClickMethod.bind(this,index)}
                            />
                        )
                    })}
                </List>
            </div>
        );
    }
}

Use React state for something like this:

class MyComp extends Component {
    constructor(props) {
        super(props);
        this.state = {
          currentSelectedItem: ''
        };
        this.onClickMethod = this.onClickMethod.bind(this);
    }
    onClickMethod() {
       // removed for brevity
       this.setState({ currentSelectedItem: pp.name });  // You must somehow manage to get the pp.name from the array here, assuming it is unique 
    }
    render() {
        return (
            <div>
                <List>
                    {this.props.myData.map(pp => {
                        return (
                            <ListItem key={pp.name}
                                      style={(this.state.currentSelectedItem === pp.name)?
                                        styles.listItemClicked : styles.listItem}
                                      primaryText={pp.name}
                                      onClick={this.onClickMethod}
                            />
                        )
                    })}
                </List>
            </div>
        );
    }
}

Not the answer you're looking for? Browse other questions tagged or ask your own question.