Método pai de chamada ReactJS

140

Estou dando o primeiro passo no ReactJS e tentando entender a comunicação entre pais e filhos. Como estou criando um formulário, tenho o componente para estilizar campos. E também tenho componente pai que inclui campo e verificá-lo. Exemplo:

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

Há alguma forma de fazer isso. E minha lógica é boa no "mundo" do reactjs? Obrigado pelo seu tempo.

KaronatoR
fonte

Respostas:

154

Para fazer isso, você passa um retorno de chamada como uma propriedade para o filho do pai.

Por exemplo:

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

No exemplo acima, Parentchama Childcom uma propriedade de valuee onChange. O Childretorno in vincula um onChangemanipulador a um <input />elemento padrão e passa o valor para o Parentretorno de chamada do, se definido.

Como resultado, o Parent's changeHandlermétodo é chamado com o primeiro argumento é o valor da cadeia do <input />campo no Child. O resultado é que o Parentestado do pode ser atualizado com esse valor, fazendo com que o <span />elemento do pai seja atualizado com o novo valor conforme você o digita no Childcampo de entrada do.

Mike Driver
fonte
15
Acho que você precisa para ligar a função dos pais antes de passá-lo para a criança:<Child value={this.state.value} onChange={this.changeHandler.bind(this)} />
O01
19
@ o01 não, você não porque eu estou usando React.createClassqual auto vincula todos os métodos de componentes. Se eu estava usando Reagir aulas ES6 então você precisa vinculá-lo (a menos que você estava no construtor de ligação automática que é o que um monte de pessoas estão fazendo estes dias para contornar esta situação)
Mike Motorista
1
@ MikeDriver eu vejo. Não sabia que isso era limitado a casos que utilizavam classes ECMAScript 6 (que eu sou). Também não sabia que a equipe do React recomenda a ligação automática no construtor.
o01 4/06/15
1
Não sei se eles recomendam, mas parece ser uma coisa bastante comum. Faz mais sentido para mim do que colocar o bind dentro do thread de renderização, pelo fato de .bindretornar uma nova função, então basicamente você está criando uma nova função toda vez que executa a renderização. Isso provavelmente é bom, mas se você ligar o construtor, estará fazendo isso apenas uma vez por método de componente na instanciação, em vez de em cada renderização. É uma escolha de nit ... mas tecnicamente melhor, eu acho!
Mike Motorista
1
@ DavidLy-Gagnon bem no exemplo, pode ser indefinido, pois eu não anexei isRequired no propType. Mas sim, você pode fazer isso ou apenas verificar se foi definido ou não.
Mike Motorista
52

Você pode usar qualquer método pai. Para isso, você deve enviar esses métodos do seu pai para o seu filho como qualquer valor simples. E você pode usar muitos métodos dos pais ao mesmo tempo. Por exemplo:

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

E use-o no Child desta forma (para qualquer ação ou método filho):

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
fonte
1
Resposta brilhante. Não faço ideia de que você poderia passar métodos como adereços como este, eu tenho usado refs para conseguir isso!
22618 Paul Redmond
1
Eu recebi o retorno de chamada para ser chamado pela criança, mas lá this.propsno retorno de chamada se torna undefined.
khateeb 5/09
Você deve enviar este callback de pai para filho (tentar vincular esse retorno de chamada com this)
Vitaliy Andrusishyn
Olá Valentin Petkov. Bem-vinda!
Vitaliy Andrusishyn
39

Atualização de 2019 com react 16+ e ES6

A publicação desta publicação React.createClassfoi descontinuada da versão de reação 16 e o ​​novo Javascript ES6 oferecerá mais benefícios.

Pai

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

}

Criança

import React, {Component} from 'react';

export default class Child extends Component {

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

Filho apátrida simplificado como constante ES6

import React from 'react';

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

}
export default Child;
Fangming
fonte
Ver 4 espaços em vez de 2 no ES6 JS me deixa triste: '(
Bataleon 16/01/19
3

Passe o método do Parentcomponente para baixo como um proppara o seu Childcomponente. ou seja:

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
fonte
2

Usando a função || componente sem estado

Componente pai

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

Componente filho

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
fonte
1
Para agregar valor à sua resposta, considere adicionar uma breve explicação sobre o que esse código faz.
Cray
quando você clica no botão no componente filho, a função Chamar para o componente pai via adereços.
Omkesh Sajjanwar
1
E se a função tiver parâmetros? Como você passa os parâmetros para o pai?
alex351
sim! @ alex351, podemos lidar com esse cenário. No componente filho -> onClick = {props.handleParentFun ("YoureValue")} No componente pai -> handleParentFun = {(value) => {console.log (); handleChildFun (valor); }}
Omkesh Sajjanwar
0

Reagir 16+

Componente filho

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;

Componente pai

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
fonte