Метод батьківського виклику 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зворотного виклику 's, якщо він визначений.

У результаті Parentвикликується changeHandlerметод 's , причому перший аргумент є значенням рядка з <input />поля в Child. Результат полягає в тому, що стан Parent's може бути оновлений цим значенням, в результаті чого батьківський <span />елемент оновлюється новим значенням під час введення його в Childполе введення.


15
Я думаю, вам потрібно зв’язати батьківську функцію, перш ніж передавати її дитині:<Child value={this.state.value} onChange={this.changeHandler.bind(this)} />
0101

19
@ o01 ні, ви цього не робите, тому що я використовую, React.createClassяке автоматично пов'язує всі компоненти компонентів. Якби я використовував класи React es6, тоді вам потрібно було б прив’язати його (якщо тільки ви не автозв’язували в конструкторі, що багато людей роблять в ці дні, щоб обійти це)
Майк Драйвер

1
@MikeDriver Я бачу. Я не знав, що це обмежено випадками, що використовують ECMAScript 6 класів (що я є). Також не знали, команда React рекомендує автоматичне прив'язування в конструкторі.
o01

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} />);
    }
});

І використовуйте його в Дитині так (для будь-яких дій або будь-яких дитячих методів):

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
Щоб додати значення своїй відповіді, спробуйте додати коротке пояснення того, що робить цей код.
Cray

коли ви натискаєте кнопку в дочірньому компоненті, тоді функція Дзвінок до батьківського компонента через реквізит.
Омкеш Саджанвар

1
Що робити, якщо функція має параметри? Як ви передаєте параметри батькові?
alex351

так! @ alex351 ми можемо впоратися з таким сценарієм. В дочірніх компонентах -> onClick = {props.handleParentFun ("YoureValue")} У батьківському компоненті -> handleParentFun = {(значення) => {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.