Lucarnosky
Lucarnosky

Reputation: 514

Handle multiple child component in React

I've tried to look everywhere and couldn't find anything related to my use case, probably I'm looking for the wrong terms.

I have a situation where I have a bar with 3 icons, I'm looking for set one icon "active" by changing the class of it.

The icon is a custom component which have the following code

export default class Icon extends Component {

    state =  {
        selected : false,
    }

    setSelected = () => {
        this.setState({
            selected : true
        })
    }
    
    setUnselected = () => {
        this.setState({
            selected : false
        })
    }

    render() {
        var classStatus = '';
        if(this.state.selected)
            classStatus = "selected-icon"
        else
            classStatus = "icon"
        return <div className={classStatus} onClick={this.props.onClick}><FontAwesomeIcon icon={this.props.icon} /></div>
    }
}

In my parent component I have the following code

export default class MainPage extends Component {

    handleClick(element) {
        console.log(element);
        alert("Hello!");
    }

    render() {
        return (
            <div className="wrapper">
                <div className="page-header">
                    <span className="menu-voice">File</span>
                    <span className="menu-voice">Modifica</span>
                    <span className="menu-voice">Selezione</span>
                </div>
                <div className="page-main">
                    <span className="icon-section">
                        <div className="top-icon">
                            <Icon icon={faFileCode} onClick={() => this.handleClick(this)} />
                            <Icon icon={faCodeBranch} onClick={() => this.handleClick(this)} />
                            <Icon icon={faMagnifyingGlass} onClick={() => this.handleClick(this)} />
                        </div>
                    </span>
                    <span className="files-section">Files</span>
                    <span className="editor-section"></span>
                </div>
                <div className="page-footer">
                    Footer
                </div>
            </div>
        );
    }
}

What I'm trying to achieve is that when one of the Icon child component get clicked it will set the selected state to true manage by the parent component, in the same time while one of them is true I would like that the parent would set to false the other twos.

I've tried to use the useRef function but it doesn't look as a best practise. Which is the correct way to do it? Sending also this to the handleClick function it just return the MainPage class instead of the child. Any suggestion at least where I should watch?

Thanks in advance

Upvotes: 0

Views: 816

Answers (2)

Chad S.
Chad S.

Reputation: 6633

I suggest not storing the state in the icon, since it doesn't know what else you're using it for. Simply have the icon component take it's 'selected' status from props. e.g.

export default class Icon extends Component {
  render() {
    var classStatus = '';
    if(this.props.selected)
      classStatus = "selected-icon"
    else
      classStatus = "icon"
    
     return (
      <div className={classStatus} onClick={this.props.onClick}>. 
        <FontAwesomeIcon icon={this.props.icon} />
      </div>
     );
    }
};

Then you can just manage the state in the parent where it should be:

export default class MainPage extends Component {
  constructor(props) {
    super(props);
    this.state = { selectedOption : '' };
  }

  handleSelectOption(newValue) {
    this.setState({ selectedOption: newValue });
  }

  isSelected(value) {
    return value === this.state.selectedOption;
  }

  render() {
    return (
      <div className="wrapper">
      { /* etc... */ }
      <div className="page-main">
        <span className="icon-section">
          <div className="top-icon">
            <Icon 
               icon={faFileCode} 
               onClick={() => this.handleSelectOption("File")} 
               selected={isSelected("File")}
            />
            <Icon 
               icon={faCodeBranch} 
               onClick={() => this.handleSelectOption("Modifica")}
               selected={isSelected("Modifica")} 
            />
            { /* etc... */ }
          </div>
        </span>
      </div>       
      { /* etc... */ }
    </div>
    );
  }
};

Upvotes: 2

Fred
Fred

Reputation: 286

You should define a constructor in your class component:

        constructor(props) {
          super(props);
          this.state = { selected : false };

        }

You also have to call a function which modify the state when you click on the Icon. onClick={this.props.onClick} doesn't change the state

Upvotes: 0

Related Questions