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!
    }
})

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

Ответы:


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;

Видя 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>
)

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;
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.