Вызов родительской функции в дочернем компоненте

Я пытаюсь обернуть один компонент другим и вызвать функцию из этого «одного» компонента.

<Parent>
    <Child1>
    <button
        onClick = {
        //toggleSomething
        console.info("Run function `toggleSomething` from parent")
        }
    >
        Change state 1
    </button>
    </Child1>

    <Child2>
    <button
        onClick = {
        //toggleSomething
        console.info("Run function `toggleSomething` from parent")
        }
    >
        Change state 2
    </button>
    </Child2>
</Parent>

а в родительском компоненте у меня есть:

class Parent extends React.Component {
  state = {
    something: false
  };

  toggleSomething = () => {
    this.setState({
      something: true
    });
  };

  render() {
    return <div className = "parentClasses">{this.props.children}</div>;
  }
}

Вот площадка: https://codesandbox.io/s/1ykllwnyq3

Для этого есть решение?

передайте свою функцию как реквизит дочернему элементу.

Shubham Agarwal Bhewanewala 24.07.2018 18:04
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
1
64
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

class App extends React.Component {
  render() {
    return (
      <div>
        <Parent>
          <Child1 />
          <Child2 />
        </Parent>
      </div>
    );
  }
}

class Parent extends React.Component {
  state = {
    something: false
  };

  toggleSomething = () => {
    console.info("now toggling !!");
    this.setState({
      something: true
    });
  };

  render() {
    const reactChildren = React.Children.toArray(this.props.children);
    const childrenWithProps = reactChildren.map(element =>
      React.cloneElement(element, {
        toggleSomething: this.toggleSomething
      })
    );
    return <div className = "parentClasses">{childrenWithProps}</div>;
  }
}

const Child1 = props => {
  return (
    <div class = "someClasses">
      <button
        onClick = {
          //toggleSomething
          () => {
            props.toggleSomething();
            console.info("Run function `toggleSomething` from parent");
          }
        }
      >
        Change state 1
      </button>
    </div>
  );
};


const Child2 = props => {
  return (
    <div class = "someOtherClasses">
      <button
        onClick = {() => {
          debugger;
          props.toggleSomething();
          console.info("Run function `toggleSomething` from button 2");
        }}
      >
        Change state 2
      </button>
    </div>
  );
};

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<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 = "root"></div>.

Now the content of Child 2 and Child1 can be rendered according to props let say tomorrow, you want something else for Child 2 view. you can change your child Component like this.

const Child2 = props => {
      const { RenderView, toggleSomething } = props
      //renderView is your view Component(stateless/statefull)
      return (
      <div class = "someOtherClasses">
        {<RenderView toggleSomething = {toggleSomething} />}
      </div>
      );
    };

Как насчет такого подхода?

Это не сработает, если я хочу иметь динамический контент внутри <Child1> и <Child2>.

Rst00 24.07.2018 17:55

Да, ты прав. Позвольте мне отредактировать ответ, используя другой подход, который вы можете сделать расширяемым. Проблема в том, что у вас есть контекст родительского компонента. вы не можете получить доступ к опоре, переданной там child1 или child2. Вам нужно написать это как другой компонент. И там вы можете иметь различные шаблоны

simbathesailor 24.07.2018 17:58

Этого все еще недостаточно. Он будет использоваться во многих местах, поэтому должен быть динамичным. Допустим, этот <Parent> - обертка, а <Child1> с <Child2> - стороны - левая и правая. Стандартным является то, что Child1 виден пользователю, а Child2 - нет. Если я нажму кнопку в Child1, состояние Parent должно измениться и добавить CSS, чтобы показать Child2 и скрыть Child1. У Child2 также есть кнопка с таким же действием, чтобы вы могли «двигаться вперед» и «назад». Например, нажмите «Забыли пароль» в Child1, и тогда появится Child2 с формой и кнопкой «вернуться» к Child1. Вот почему мне нужно использовать его как <Child1></Child1>

Rst00 24.07.2018 18:13

Прямо сейчас ваши Child1 и Child2 ничего не делают, только заполнитель. Вы просто возвращаете props.children. Вы можете визуализировать различные компоненты с разной логикой, передаваемой как RenderView из любого места в Child1 в упомянутом выше дизайне. Вы в основном получаете то же поведение ... Я не могу придумать, как это сделать без тех изменений, которые я сделал. Я уже упоминал в предыдущем комментарии, почему это невозможно. Спасибо

simbathesailor 24.07.2018 18:18

Вам нужно передать функцию и получить к ней доступ из props. Clone Element позволяет добавить опору всем дочерним элементам.

import React from "react";
import ReactDOM from "react-dom";

const Child1 = props => {
  return <button onClick = {props.handler}>test</button>;
};

class Parent extends React.Component {
  state = {
    something: "nope"
  };

  toggleSomething = () => {
    this.setState({
      something: "yes"
    });
  };

  render() {


    const childrenWithProps = React.Children.map(
      this.props.children, child =>
          React.cloneElement(
          child, { handler: this.toggleSomething }
            )
      );

    return <div className = "parentClasses">
    {this.state.something}
      {childrenWithProps}   
    </div>;
  }
}

const App = () => 
    <Parent>
        <Child1/> 
    </Parent>

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Проблема в том, что мне нужно передать содержимое в компонент <Child1>. Будет форма с кнопкой, и эта кнопка должна вызывать действие. Я бы использовал эти компоненты <Parent> и <Child1> в нескольких местах, поэтому они должны быть «динамическими».

Rst00 24.07.2018 17:50

Мой ответ: pastebin.com/ELekzcgQ В комментарии я не могу вставить код.

Rst00 24.07.2018 17:54
Ответ принят как подходящий

Принимая на себя ответственность за эти компоненты:

  • Parent: Береги состояние.
  • Child1 и Child2: универсальный контейнер пользовательского интерфейса.
  • App: Заботится о том, как отображается состояние Parent.

Это можно сделать с помощью техники рендерить реквизит.

В приведенном ниже примере вместо передачи элемента в качестве дочернего элемента <Parent> используется вместо этого передается функция.

class App extends React.Component {
  render() {
    return (
      <div>
        <Parent>
          {toggle => (
            <React.Fragment>
              <Child1>
                <button onClick = {toggle}>Change state 1</button>
              </Child1>
              <Child2>
                <button onClick = {toggle}>Change state 2</button>
              </Child2>
            </React.Fragment>
          )}
        </Parent>
      </div>
    );
  }
}

class Parent extends React.Component {
  state = {
    something: false
  };

  toggleSomething = () => {
    this.setState({
      something: true
    });
  };

  render() {
    return (
      <div className = "parentClasses">
        {this.state.something.toString()}
        {this.props.children(this.toggleSomething)}
      </div>
    );
  }
}

const Child1 = props => {
  return <div class = "someClasses">{props.children}</div>;
};

const Child2 = props => {
  return <div class = "someOtherClasses">{props.children}</div>;
};

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<script crossorigin src = "https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src = "https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id = "root"></div>

Вот и все. Прекрасно работает. Большое спасибо!

Rst00 24.07.2018 19:03

Другие вопросы по теме