peter flanagan
peter flanagan

Reputation: 9790

React - only one "active" child component at any one time

I have a parent component that holds a number of children components. I want to add an active className to a a child component when it is clicked on.

This is working, but the issue is that each child component can have an active classname. Only one of the components should have be active each time.

Does anyone have any idea how to solve this issue?

Please see my code below.

class MyComponent extends Component {

    constructor(props) {
        super(props);
        this.addActiveClass= this.addActiveClass.bind(this);

        this.state = {
            active: false,
        };
    }

    addActiveClass() {
        const currentState = this.state.active;
        this.setState({ active: !currentState });
    };

    render() {
        return (
            <div 
                className={this.state.active ? 'active': null} 
                onclick={this.addActiveClass} 
            >
                <p>{this.props.text}</p>
            </div>
        )
  }
}

class Test extends Component {
    render() {
        return (
            <div>
                <MyComponent text={'1'} />
                <MyComponent text={'2'} />
                <MyComponent text={'3'} />
                <MyComponent text={'4'} />
            </div>
        );
    }
}

Upvotes: 3

Views: 3189

Answers (1)

Jordan Enev
Jordan Enev

Reputation: 18674

Add the active functionality to your Test Component.

There you can check whether there is already active Component or not.

class MyComponent extends React.Component {

    render() {
        return <div 
            id={this.props.id}
            className={this.props.active ? 'active': null} 
            onClick={this.props.handleClick} >
                {this.props.text}
        </div>
  }
}

class Test extends React.Component {

    constructor(props) {
        super(props);

        this.state = {
            components: [
                {id: 1, text: 1},
                {id: 2, text: 2},
                {id: 3, text: 3},
                {id: 4, text: 4}
            ],
            activeID: null
        };
    }
    
    handleClick(e) {
        // If there is already active component ID, don't set another one!
        // We support only one active ID.
        if (this.state.activeID !== null) return;
        
        const id = parseInt(e.target.id);
        this.setState({
            activeID: id
        });
    }
    
    renderComponents() {
        return (this.state.components.map( c =>
            <MyComponent
                id={c.id}
                active={c.id === this.state.activeID}
                text={c.text}
                handleClick={this.handleClick.bind(this)} /> ));
    }
    
    renderActiveIDText() {
        return (this.state.activeID ? <p>{"Active Component ID: " + this.state.activeID}</p> : null );
    }

    render() {
        return <div>
            {this.renderActiveIDText()}
            {this.renderComponents()}
        </div>
    }
}

ReactDOM.render(<Test />, document.getElementById('container'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="container">
    <!-- This element's contents will be replaced with your component. -->
</div>

Upvotes: 3

Related Questions