Как вызвать метод из другого компонента, чтобы заставить параметр onClick работать

#reactjs

#reactjs

Вопрос:

У меня есть два компонента: Main и LeftMenu. В компоненте LeftMenu есть значок. Желаемая функциональность: нажатие на значок покажет / скроет элемент из основного компонента.

Я могу настроить желаемую функциональность, работающую при добавлении значка FaDropbox в основной компонент. Но когда я пытаюсь поместить его в компонент LeftMenu, он не работает.

Основной компонент со значком FaDropbox работает:

 class Main extends Component {
  state = {
    isShowTiles: true
  };

  render() {
    return (
      <div className="Main">
        {/* Background color set with Helmet */}
        <Helmet>
          <style>{"body { background-color: #1A2C3B; }"}</style>
        </Helmet>
        <div className="Container">
          <Row className="RowHeader">
            <Header
              user={this.props.user}
              photo={this.props.photo}
              userProfile={this.props.userProfile}
            />
          </Row>
          <Row>
            <div class="toggleArea">
              {this.state.isShowTiles ? <Tiles /> : <BoxTiles />}
            </div>
          </Row>
        </div>
        <button onClick={this.toggleComponents}>
          <FaDropbox />
        </button>
      </div>
    );
  }

  toggleComponents = () => {
    this.setState({
      isShowTiles: !this.state.isShowTiles
    });
  };
}

export default Main;
  

Когда я пытаюсь вызвать toggleComponents из компонента LeftMenu на значке FaDropbox, это не работает.

 class LeftMenu extends Component {
  render() {
    return (
      <div className="LeftMenu">
        {/* Base Layout */}
        <div className="LeftContainer">
          <Row className="justify-content-md-center">
            <div className="LeftIcon">
              {/* <FaDropbox/> */}
              <button onClick={toggleComponents}>
                <FaDropbox />
              </button>
            </div>
          </Row>
        </div>
      </div>
    );
  }
}

export default LeftMenu;
  

Я пытался экспортировать метод toggleComponents из основного компонента, как показано ниже, но это не сработало:

 export function toggleComponents() {
  return this.toggleComponents;
}
  

Ожидаемый результат — заставить значок FaDropbox иметь параметр onClick, работающий, но в компоненте LeftMenu. Я не хочу иметь FaDropbox в главном компоненте. Как этого добиться и правильно вызвать этот метод извне основного компонента?

Комментарии:

1. где вы визуализируете компонент LeftMenu?

Ответ №1:

Вам нужно передать toggleComponents в качестве реквизита в LeftMenu.

<LeftMenu toggleComponents = {this.toggleComponents}/>

Затем вы можете просто вызвать его внутри LeftMenu, как показано ниже

<button onClick={() => this.props.toggleComponents()}><FaDropbox/></button>

Ответ №2:

Добавьте функцию toggleComponents в класс LeftMenu и используйте ее так же, как в Main

 <button onClick={this.toggleComponents}><FaDropbox/></button>
  

Помните о this привязке в классе:
https://reactjs.org/docs/handling-events.html

Вы также можете передать toggleComponents функцию в LeftMenu

 <LeftMenu toggleComponents={this.toggleComponents} />

class LeftMenu extends Component {
  render() {
    return (
      ...
      <button onClick={this.props.toggleComponents}><FaDropbox/></button>
    )
  }
}
  

Комментарии:

1. Как передать эту функцию классу LeftMenu? В форме, подобной <LeftMenu />, нет LeftMenu …

2. Вам нужно где-то отобразить LeftMenu Один из способов — использовать его как HTML-тег <LeftMenu />, например, в вашем Main классе. Или вы можете использовать так называемый render props метод: reactjs.org/docs/render-props.html

3. Дело в том, что я не хочу иметь LeftMenu в Main, потому что он дублирует компонент LeftMenu… При добавлении я вижу LeftMenu два раза, и новый его экземпляр фактически выполняет задание onClick, но в целом это не ожидаемый результат.

4. Затем создайте оболочку для обоих компонентов, например, App класс с двумя компонентами LeftMenu и Main , toggleComponents функция может быть передана из App (если я вас правильно понимаю)

Ответ №3:

Вы не предоставили соединения между двумя компонентами. Хотя мне нравится (минималистская версия)

У вас есть компонент макета

 class Layout extends Component {
  state = {
    isShowTiles: true
  };
  toggleComponents = () => {
    this.setState({
      isShowTiles: !this.state.isShowTiles
    });
  };
  render() {
    return (
      <div class="layout">
        <Main isShowTiles={this.state.isShowTiles} />
        <LeftMenu toggleComponents={this.toggleComponents} />
      </div>
    );
  }
}
  

И в главном компоненте:

 class Main extends Component {
  render() {
    return (
      <div class="toggleArea">
        {this.props.isShowTiles ? "Title" : "Box Title"}
      </div>
    );
  }
}
  

И компонент LeftMenu:

 class LeftMenu extends Component {
  render() {
    return <button onClick={this.props.toggleComponents}>Click me!</button>;
  }
}
  

Проверьте:https://codesandbox.io/s/943nkvzrno

Комментарии:

1. Спасибо, у меня это работает. Теперь я думаю, как параметризовать это, я имею в виду, использовать ту же функцию, но для другого значка, и решить, какие компоненты показывать / скрывать.

Ответ №4:

 import LeftMenu from 'leftMenu';
class Main extends Component{
    state ={
        isShowTiles:true
    };

    toggleComponents=()=>{
        this.setState({
            isShowTiles:!this.state.isShowTiles
        })
    }
    render() {
        return (
            <div className="Main">
                {/* Background color set with Helmet */}
                <Helmet>
                    <style>{'body { background-color: #1A2C3B; }'}</style>
                </Helmet>
                <div className="Container">
                    <Row className="RowHeader">
                        <Header user={this.props.user} photo={this.props.photo} userProfile={this.props.userProfile} />
                    </Row>
                    <Row>
                        <div class="toggleArea">
                            { this.state.isShowTiles ? <Tiles /> : <BoxTiles/> }
                        </div>
                    </Row>
                </div>
                <LeftMenu toggleComponents={this.toggleComponents} />
            </div> 
        );
    }
}

export default Main;
  

Компонент левого меню :

 class LeftMenu extends Component {
    render() {
        const { toggleComponents } = this.props;
        return (
            <div className="LeftMenu">
                {/* Base Layout */}
                <div className="LeftContainer">
                    <Row className="justify-content-md-center">
                        <div  className="LeftIcon">
                        {/* <FaDropbox/> */}
                            <button onClick={toggleComponents}><FaDropbox/></button>
                        </div>
                    </Row>
                </div>
            </div> 
        );
    }
}
export default LeftMenu;
  

Комментарии:

1. Вы должны знать понятия состояния и реквизита в react.

2. Идея состоит в том, чтобы не иметь LeftMenu в главном компоненте. <LeftMenu toggleComponents={this.toggleComponents} /> дублирует LeftMenu, который не нужен.

3. Извините, я не понял вашего требования … можете ли вы объяснить, чего вы хотите?