Metoda rodzica wywołania ReactJS

140

Robię pierwszy krok w ReactJS i próbuję zrozumieć komunikację między rodzicem a dziećmi. Robię formę, więc mam komponent do stylizacji pól. Mam też komponent nadrzędny, który zawiera pole i je sprawdza. Przykład:

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

Czy jest jakiś sposób, aby to zrobić. I czy moja logika jest dobra w „świecie” reakcji? Dziękuję za Twój czas.

KaronatoR
źródło

Odpowiedzi:

154

Aby to zrobić, przekazujesz wywołanie zwrotne jako właściwość dziecku od rodzica.

Na przykład:

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

W powyższym przykładzie Parentwywołania Childz właściwością valuei onChange. ChildW zamian wiąże onChangeobsługi do standardowego <input />elementu i przekazuje się do wartości Parentjest zwrotna jeśli jest zdefiniowana.

W rezultacie wywoływana jest metoda Parent's changeHandlerz pierwszym argumentem będącym wartością ciągu z <input />pola w Child. W rezultacie Parentstan można zaktualizować o tę wartość, powodując <span />aktualizację elementu nadrzędnego o nową wartość w miarę wpisywania jej w Childpolu wejściowym.

Mike Driver
źródło
15
Myślę, że musisz powiązać funkcję rodzica przed przekazaniem jej dziecku:<Child value={this.state.value} onChange={this.changeHandler.bind(this)} />
o01
19
@ o01 nie, nie możesz, ponieważ używam tego, React.createClassktóry automatycznie wiąże wszystkie metody składników. Gdybym używał klas React es6, musiałbyś go powiązać (chyba że byłeś automatycznie wiązany w konstruktorze, co obecnie robi wiele osób, aby to obejść)
Mike Driver
1
@MikeDriver widzę. Nie wiedziałem, że jest to ograniczone do przypadków wykorzystujących klasy ECMAScript 6 (którym jestem). Nie był też świadomy, że zespół React zaleca automatyczne wiązanie w konstruktorze.
o01
1
Nie wiem, czy to zalecają, ale wydaje mi się, że jest to dość powszechna rzecz. Ma to dla mnie więcej sensu niż umieszczanie bind wewnątrz wątku renderującego, ponieważ powód .bindzwraca nową funkcję, więc w zasadzie tworzysz nową funkcję za każdym razem, gdy uruchamiasz render. Prawdopodobnie jest to w porządku, ale jeśli tworzysz bind w konstruktorze, robisz to tylko raz na metodę komponentu podczas tworzenia instancji, a nie przy każdym renderowaniu. To dłubie ... ale chyba technicznie ładniejsze!
Mike Driver
1
@ DavidLy-Gagnon w tym przykładzie może być niezdefiniowane, ponieważ nie dołączyłem isRequired do właściwości propType. Ale tak, możesz to zrobić lub po prostu sprawdzić, czy zostało to zdefiniowane, czy nie.
Mike Driver
52

Możesz użyć dowolnej metody nadrzędnej. W tym celu powinieneś wysłać te metody od swojego rodzica do dziecka, jak każdą prostą wartość. Możesz jednocześnie korzystać z wielu metod od rodzica. Na przykład:

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

I użyj tego w Child w ten sposób (dla dowolnych działań lub jakichkolwiek metod potomnych):

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} />);
    }
});
Vitaliy Andrusishyn
źródło
1
Świetna odpowiedź. Nie mam pojęcia, że ​​możesz przekazywać metody jako rekwizyty takie jak ten, używam referencji, aby to osiągnąć!
Paul Redmond,
1
Otrzymałem oddzwonienie, które ma zostać wywołane przez dziecko, ale this.propsw oddzwonieniu pojawia się undefined.
khateeb
Powinieneś wysłać to oddzwonienie od rodzica do dziecka (spróbuj powiązać to oddzwonienie z this)
Vitaliy Andrusishyn
Cześć Valentin Petkov. Witamy!
Vitaliy Andrusishyn
39

Aktualizacja 2019 z udziałem React 16+ i ES6

Publikowanie tego, ponieważ React.createClassjest przestarzałe w wersji 16, a nowy Javascript ES6 zapewni Ci więcej korzyści.

Rodzic

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

}

Dziecko

import React, {Component} from 'react';

export default class Child extends Component {

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

Uproszczone dziecko bezpaństwowe jako stała ES6

import React from 'react';

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

}
export default Child;
Fangming
źródło
Widok 4 spacji zamiast 2 w ES6 JS sprawia, że ​​jestem smutny: '(
Bataleon
3

Przekaż metodę z Parentkomponentu w dół jako a propdo swojego Childkomponentu. to znaczy:

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
źródło
2

Korzystanie z funkcji || składnik bezstanowy

Komponent nadrzędny

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

Komponent podrzędny

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>
         </>
        );
}
Omkesh Sajjanwar
źródło
1
Aby dodać wartość do swojej odpowiedzi, rozważ dodanie krótkiego wyjaśnienia, co robi ten kod.
Cray
kiedy klikniesz przycisk w komponencie potomnym, następnie wywołaj funkcję komponentu nadrzędnego za pomocą właściwości.
Omkesh Sajjanwar
1
A jeśli funkcja ma parametry? Jak przekazujesz parametry rodzicowi?
alex351
tak! @ alex351 poradzimy sobie z tym scenariuszem. W składniku podrzędnym -> onClick = {props.handleParentFun ("YoureValue")} W składniku nadrzędnym -> handleParentFun = {(value) => {console.log (); handleChildFun (wartość); }}
Omkesh Sajjanwar
0

Reaguj 16+

Komponent podrzędny

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;

Komponent nadrzędny

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;
Sandeep Shekhawat
źródło