ReactJS вызывает родительский метод

140

Я делаю свой первый шаг в ReactJS и пытаюсь понять общение между родителями и детьми. Я делаю форму, поэтому у меня есть компонент для оформления полей. А также у меня есть родительский компонент, который включает поле и проверяет его. Пример:

var LoginField = React.createClass({
    render: function() {
        return (
            <MyField icon="user_icon" placeholder="Nickname" />
        );
    },
    check: function () {
        console.log ("aakmslkanslkc");
    }
})

var MyField = React.createClass({
    render: function() {
...
    },
    handleChange: function(event) {
//call parent!
    }
})

Есть ли способ сделать это. И хороша ли моя логика в "мире" реагирования? Спасибо за ваше время.

KaronatoR
источник

Ответы:

154

Для этого вы передаете обратный вызов в качестве свойства дочернему элементу от родителя.

Например:

var Parent = React.createClass({

    getInitialState: function() {
        return {
            value: 'foo'
        }
    },

    changeHandler: function(value) {
        this.setState({
            value: value
        });
    },

    render: function() {
        return (
            <div>
                <Child value={this.state.value} onChange={this.changeHandler} />
                <span>{this.state.value}</span>
            </div>
        );
    }
});

var Child = React.createClass({
    propTypes: {
        value:      React.PropTypes.string,
        onChange:   React.PropTypes.func
    },
    getDefaultProps: function() {
        return {
            value: ''
        };
    },
    changeHandler: function(e) {
        if (typeof this.props.onChange === 'function') {
            this.props.onChange(e.target.value);
        }
    },
    render: function() {
        return (
            <input type="text" value={this.props.value} onChange={this.changeHandler} />
        );
    }
});

В приведенном выше примере Parentвызовы Childсо свойством valueи onChange. ChildВ свою очередь связывает onChangeобработчик со стандартным <input />элементом , и передает значение вплоть до Parent«ы обратного вызова , если он определен.

В результате Parent«S changeHandlerметод вызывается с первым аргументом является строковое значение из <input />поля в Child. В результате Parentсостояние s может быть обновлено с помощью этого значения, в результате чего родительский <span />элемент будет обновляться с новым значением по мере его Childввода в поле ввода.

Майк Драйвер
источник
15
Я думаю, что вам нужно связать родительскую функцию перед тем, как передать ее ребенку:<Child value={this.state.value} onChange={this.changeHandler.bind(this)} />
o01
19
@ o01 нет, нет, потому что я использую, React.createClassкоторый автоматически связывает все методы компонентов. Если бы я использовал классы React es6, вам нужно было бы связать его (если вы не использовали автоматическое связывание в конструкторе, что многие люди делают в эти дни, чтобы обойти это)
Майк Драйвер,
1
@MikeDriver я вижу. Не знал, что это было ограничено случаями, использующими классы ECMAScript 6 (которым я являюсь). Также не было известно, что команда React рекомендует автоматическое связывание в конструкторе.
01
1
Я не знаю, рекомендуют ли они это, но я вижу, что это довольно распространенная вещь. Для меня это имеет больше смысла, чем помещать связывание в поток рендеринга, так как причина .bindвозвращает новую функцию, поэтому в основном вы создаете новую функцию каждый раз, когда запускаете рендер. Это, вероятно, хорошо, но если вы связываете в конструкторе, то вы делаете это только один раз для метода компонента при создании экземпляра, а не при каждом рендеринге. Это придирки ... но технически лучше, я думаю!
Майк Драйвер
1
@ DavidLy-Gagnon в этом примере это может быть неопределенно, так как я не добавил isRequired в propType. Но да, вы можете либо сделать это, либо просто проверить, было ли оно определено или нет.
Майк Драйвер
52

Вы можете использовать любые родительские методы. Для этого вам следует отправить этот метод от вашего родителя к вашему ребенку, как любое простое значение. И вы можете использовать много методов от родителя одновременно. Например:

var Parent = React.createClass({
    someMethod: function(value) {
        console.log("value from child", value)
    },
    someMethod2: function(value) {
        console.log("second method used", value)
    },
    render: function() {
      return (<Child someMethod={this.someMethod} someMethod2={this.someMethod2} />);
    }
});

И используйте его в Child следующим образом (для любых действий или для любых дочерних методов):

var Child = React.createClass({
    getInitialState: function() {
      return {
        value: 'bar'
      }
    },
    render: function() {
      return (<input type="text" value={this.state.value} onClick={this.props.someMethod} onChange={this.props.someMethod2} />);
    }
});
Виталий Андрушишин
источник
1
Блестящий ответ. Понятия не имею, что вы могли бы передавать методы, как этот подпорки, я использовал ссылки для достижения этой цели!
Пол Редмонд
1
Я получил обратный вызов, который будет вызывать ребенок, но там this.propsв обратном вызове становится undefined.
khateeb
Вы должны отправить этот обратный вызов от родителя к ребенку (попробуйте связать этот обратный вызов с this)
Виталий Андрушишин,
Привет Валентин Петков. Добро пожаловать!
Виталий Андрушишин
39

2019 Обновление с реакцией 16+ и ES6

Публикация этого сообщения React.createClassисключена из версии 16 реагирования, а новый Javascript ES6 даст вам больше преимуществ.

родитель

import React, {Component} from 'react';
import Child from './Child';
  
export default class Parent extends Component {

  es6Function = (value) => {
    console.log(value)
  }

  simplifiedFunction (value) {
    console.log(value)
  }

  render () {
  return (
    <div>
    <Child
          es6Function = {this.es6Function}
          simplifiedFunction = {this.simplifiedFunction} 
        />
    </div>
    )
  }

}

ребенок

import React, {Component} from 'react';

export default class Child extends Component {

  render () {
  return (
    <div>
    <h1 onClick= { () =>
            this.props.simplifiedFunction(<SomethingThatYouWantToPassIn>)
          }
        > Something</h1>
    </div>
    )
  }
}

Упрощенный ребенок без гражданства как константа ES6

import React from 'react';

const Child = () => {
  return (
    <div>
    <h1 onClick= { () =>
        this.props.es6Function(<SomethingThatYouWantToPassIn>)
      }
      > Something</h1>
    </div>
  )

}
export default Child;
Fangming
источник
Видя 4 пробела вместо 2 в ES6, JS меня огорчает: '(
Bataleon
3

Передайте метод от Parentкомпонента вниз как propк вашему Childкомпоненту. то есть:

export default class Parent extends Component {
  state = {
    word: ''
  }

  handleCall = () => {
    this.setState({ word: 'bar' })
  }

  render() {
    const { word } = this.state
    return <Child handler={this.handleCall} word={word} />
  }
}

const Child = ({ handler, word }) => (
<span onClick={handler}>Foo{word}</span>
)
Jonca33
источник
2

Используя функцию || компонент без состояния

Родительский компонент

 import React from "react";
 import ChildComponent from "./childComponent";

 export default function Parent(){

 const handleParentFun = (value) =>{
   console.log("Call to Parent Component!",value);
 }
 return (<>
           This is Parent Component
           <ChildComponent 
             handleParentFun={(value)=>{
               console.log("your value -->",value);
               handleParentFun(value);
             }}
           />
        </>);
}

Дочерний компонент

import React from "react";


export default function ChildComponent(props){
  return(
         <> This is Child Component 
          <button onClick={props.handleParentFun("YoureValue")}>
            Call to Parent Component Function
          </button>
         </>
        );
}
Омкеш Саджанвар
источник
1
Чтобы повысить ценность своего ответа, подумайте о том, чтобы добавить краткое объяснение того, что делает этот код.
Крэй,
когда вы нажимаете кнопку в дочернем компоненте, то вызываете функцию родительского компонента через реквизит.
Омкеш Саджанвар
1
Что если функция имеет параметры? Как вы передаете параметры родителю?
alex351
да! @ alex351 мы справимся с этим сценарием. В родительском компоненте -> onClick = {props.handleParentFun ("YoureValue")} В родительском компоненте -> handleParentFun = {(value) => {console.log (); handleChildFun (значение); }}
Омкеш Саджанвар
0

Реакция 16+

Дочерний компонент

import React from 'react'

class ChildComponent extends React.Component
{
    constructor(props){
        super(props);       
    }

    render()
    {
        return <div>
            <button onClick={()=>this.props.greetChild('child')}>Call parent Component</button>
        </div>
    }
}

export default ChildComponent;

Родительский компонент

import React from "react";
import ChildComponent from "./childComponent";

class MasterComponent extends React.Component
{
    constructor(props)
    {
        super(props);
        this.state={
            master:'master',
            message:''
        }
        this.greetHandler=this.greetHandler.bind(this);
    }

    greetHandler(childName){
        if(typeof(childName)=='object')
        {
            this.setState({            
                message:`this is ${this.state.master}`
            });
        }
        else
        {
            this.setState({            
                message:`this is ${childName}`
            });
        }

    }

    render()
    {
        return <div>
           <p> {this.state.message}</p>
            <button onClick={this.greetHandler}>Click Me</button>
            <ChildComponent greetChild={this.greetHandler}></ChildComponent>
        </div>
    }
}
export default  MasterComponent;
Сандип Шехават
источник