Método primario de llamada ReactJS

140

Estoy dando mi primer paso en ReactJS e intento entender la comunicación entre padres e hijos. Estoy formando, así que tengo el componente para los campos de estilo. Y también tengo un componente principal que incluye el campo y verificarlo. Ejemplo:

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

Hay alguna forma de hacerlo. ¿Y mi lógica es buena en reaccionar "mundo"? Gracias por tu tiempo.

KaronatoR
fuente

Respuestas:

154

Para hacer esto, pasa una devolución de llamada como una propiedad al padre desde el padre.

Por ejemplo:

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

En el ejemplo anterior, las Parentllamadas Childcon una propiedad de valuey onChange. A Childcambio, vincula un onChangecontrolador a un <input />elemento estándar y pasa el valor a la Parentdevolución de llamada si está definido.

Como resultado , se llama al método Parent's changeHandlercon el primer argumento que es el valor de cadena del <input />campo en Child. El resultado es que el Parentestado del 's puede actualizarse con ese valor, haciendo que el <span />elemento del padre se actualice con el nuevo valor a medida que lo escribe en el Childcampo de entrada del ' s.

Mike Driver
fuente
15
Creo que debe vincular la función principal antes de pasarla al elemento secundario:<Child value={this.state.value} onChange={this.changeHandler.bind(this)} />
o01
19
@ o01 no, no, porque estoy usando el React.createClasscual enlaza automáticamente todos los métodos de componentes. Si estaba usando las clases React es6, entonces necesitarías vincularlo (a menos que estuvieras auto-vinculante en el constructor, que es lo que mucha gente está haciendo en estos días para solucionar esto)
Mike Driver
1
@ MikeDriver Ya veo. No sabía que esto se limitaba a casos que utilizaban clases ECMAScript 6 (que yo soy). Tampoco sabía que el equipo de React recomienda el enlace automático en el constructor.
o01
1
No sé si lo recomiendan, pero parece ser algo bastante común. Tiene más sentido para mí que poner el enlace dentro del hilo de renderizado, por lo que .binddevuelve una nueva función, por lo que básicamente está creando una nueva función cada vez que ejecuta render. Probablemente esto esté bien, pero si vincula el constructor, solo lo hará una vez por método de componente en la instanciación en lugar de cada render. Es muy difícil ... ¡pero técnicamente más agradable, supongo!
Mike Driver
1
@ DavidLy-Gagnon bien en el ejemplo, podría estar indefinido ya que no he agregado isRequired en el propType. Pero sí, podrías hacer eso o simplemente verificar si se definió o no.
Mike Driver
52

Puede usar cualquier método principal. Para esto, debe enviar estos métodos de su padre a su hijo como cualquier valor simple. Y puede usar muchos métodos de los padres al mismo tiempo. Por ejemplo:

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

Y úselo en el Niño de esta manera (para cualquier acción o en cualquier método hijo):

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
fuente
1
Brillante respuesta. No tengo idea de que puedas pasar métodos como accesorios como este, ¡he estado usando referencias para lograr esto!
Paul Redmond el
1
Obtuve la devolución de llamada para que la llame el niño, pero allí se hace this.propsla devolución de llamada undefined.
khateeb
Debe enviar esta devolución de llamada de padres a hijos (intente vincular esta devolución de llamada con this)
Vitaliy Andrusishyn
Hola Valentin Petkov ¡Bienvenidos!
Vitaliy Andrusishyn
39

Actualización de 2019 con react 16+ y ES6

Publicar esto ya que React.createClassestá en desuso desde la versión 16 de react y el nuevo Javascript ES6 le dará más beneficios.

Padre

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

}

Niño

import React, {Component} from 'react';

export default class Child extends Component {

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

Niño sin estado simplificado como constante ES6

import React from 'react';

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

}
export default Child;
Colmillo
fuente
Ver 4 espacios en lugar de 2 en ES6 JS me pone triste: '(
Bataleon
3

Pase el método desde el Parentcomponente hacia abajo como propa su Childcomponente. es decir:

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

Usando la función || componente sin estado

Componente principal

 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 hijo

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
fuente
1
Para agregar valor a su respuesta, considere agregar una breve explicación sobre lo que hace este código.
Cray
cuando hace clic en el botón en el componente secundario, luego llame a la función Componente principal a través de accesorios.
Omkesh Sajjanwar
1
¿Qué pasa si la función tiene parámetros? ¿Cómo pasa los parámetros al padre?
alex351
¡si! @ alex351 podemos manejar ese escenario. En el componente secundario -> onClick = {props.handleParentFun ("YoureValue")} En el componente principal -> handleParentFun = {(value) => {console.log (); handleChildFun (valor); }}
Omkesh Sajjanwar
0

Reaccionar 16+

Componente hijo

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 principal

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
fuente