React js onClick no puede pasar valor al método


639

Quiero leer las propiedades del valor del evento onClick. Pero cuando hago clic en él, veo algo así en la consola:

SyntheticMouseEvent {dispatchConfig: Object, dispatchMarker: ".1.1.0.2.0.0:1", nativeEvent: MouseEvent, type: "click", target

Mi código funciona correctamente Cuando ejecuto puedo ver {column}pero no puedo obtenerlo en el evento onClick.

Mi código:

var HeaderRows = React.createClass({
  handleSort:  function(value) {
    console.log(value);
  },
  render: function () {
    var that = this;
    return(
      <tr>
        {this.props.defaultColumns.map(function (column) {
          return (
            <th value={column} onClick={that.handleSort} >{column}</th>
          );
        })}
        {this.props.externalColumns.map(function (column) {
          // Multi dimension array - 0 is column name
          var externalColumnName = column[0];
          return ( <th>{externalColumnName}</th>);
        })}
      </tr>
    );
  }
});

¿Cómo puedo pasar un valor al onClickevento en React js?



2
considere usar uno mismo en lugar de eso. Eso es bastante engañoso, ya que debería ser sinónimo de "esto" (aunque realmente no es importante para cada uno)
Dan

Usando el método de enlace y el método de flecha podemos pasar el valor al evento
Onclick

Respuestas:


1287

Camino fácil

Use una función de flecha:

return (
  <th value={column} onClick={() => this.handleSort(column)}>{column}</th>
);

Esto creará una nueva función que llama handleSortcon los parámetros correctos.

Mejor manera

Extraerlo en un subcomponente. El problema con el uso de una función de flecha en la llamada de render es que creará una nueva función cada vez, lo que termina causando re-renderizaciones innecesarias.

Si crea un subcomponente, puede pasar el controlador y usar accesorios como argumentos, que luego se volverán a representar solo cuando los accesorios cambien (porque la referencia del controlador ahora nunca cambia):

Subcomponente

class TableHeader extends Component {
  handleClick = () => {
    this.props.onHeaderClick(this.props.value);
  }

  render() {
    return (
      <th onClick={this.handleClick}>
        {this.props.column}
      </th>
    );
  }
}

Componente principal

{this.props.defaultColumns.map((column) => (
  <TableHeader
    value={column}
    onHeaderClick={this.handleSort}
  />
))}

Old Easy Way (ES5)

Use .bindpara pasar el parámetro que desee:

return (
  <th value={column} onClick={that.handleSort.bind(that, column)}>{column}</th>
);

77
reaccionar da una advertencia cuando uso como su código. Cambio mi código a onClick = {that.onClick.bind (nulo, columna)}
user1924375

12
¿Cómo usaría esto con una <a>etiqueta donde necesita pasar el evento, para usarpreventDefault()
Simon H

38
@SimonH El evento se pasará como último argumento, después de los argumentos por los que pasó bind.
mancha

47
¿No es malo para el rendimiento? ¿No se creará una nueva función en cada render?
AndrewMcLagan

13
@AndrewMcLagan lo es. Me pareció que esta para describir la regla y la solución de los mas potente.
E. Sundin

140

Aquí hay buenas respuestas, y estoy de acuerdo con @Austin Greco (la segunda opción con componentes separados).
Hay otra forma que me gusta, curry .
Lo que puede hacer es crear una función que acepte un parámetro (su parámetro) y devuelva otra función que acepte otro parámetro (el evento de clic en este caso). entonces eres libre de hacer lo que quieras.

ES5:

handleChange(param) { // param is the argument you passed to the function
    return function (e) { // e is the event object that returned

    };
}

ES6:

handleChange = param => e => {
    // param is the argument you passed to the function
    // e is the event object that returned
};

Y lo usarás de esta manera:

<input 
    type="text" 
    onChange={this.handleChange(someParam)} 
/>

Aquí hay un ejemplo completo de tal uso:

Tenga en cuenta que este enfoque no resuelve la creación de una nueva instancia en cada render.
Me gusta este enfoque sobre los otros controladores en línea ya que este es más conciso y legible en mi opinión.

Editar:
como se sugiere en los comentarios a continuación, puede almacenar en caché / memorizar el resultado de la función.

Aquí hay una implementación ingenua:


12
Esta debería ser la respuesta aceptada. REALMENTE fácil de implementar y no necesita crear ningún otro componente o vincular de manera diferente. ¡Gracias!
Tamb

29
Se ve mejor, pero desde una perspectiva de rendimiento, el curry realmente no ayuda, porque si llamas a handleChange dos veces, con el mismo parámetro, obtienes dos funciones que el motor JS considera objetos separados, incluso si hacen lo mismo . Entonces todavía obtienes un renderizado. En aras del rendimiento, necesitaría almacenar en caché los resultados de handleChange para obtener la ventaja de rendimiento. Me gustahandleChange = param => cache[param] || (e => { // the function body })
travellingprog

66
Esta es la respuesta perfecta si cumple con los consejos de @travellingprog
llioor

2
¿Alguien puede proporcionar un enlace o explicar cómo funciona este mecanismo de almacenamiento en caché? Gracias.
Sadok Mtir

2
Hermosa y ordenada!
Hatem Alimam

117

Hoy en día, con ES6, creo que podríamos usar una respuesta actualizada.

return (
  <th value={column} onClick={()=>this.handleSort(column)} >{column}</th>
);

Básicamente, (para cualquiera que no sepa) ya onClickque espera que se le pase una función, bindfunciona porque crea una copia de una función. En su lugar, podemos pasar una expresión de función de flecha que simplemente invoca la función que queremos y conserva this. Nunca debería necesitar vincular el rendermétodo en React, pero si por alguna razón está perdiendo thisen uno de sus métodos componentes:

constructor(props) {
  super(props);
  this.myMethod = this.myMethod.bind(this);
}

10
Nunca es necesario vincular render()porque React lo llama. En todo caso, necesita bindlos controladores de eventos, y solo cuando no esté usando flechas.
Dan Abramov

1
@DanAbramov Creo que tienes razón, pero lo incluí por si acaso, actualizado con un ejemplo que no alienta implícitamente el renderizado vinculante.
aikeru

3
Tenga en cuenta que también es mejor para pasar propsa super()o this.propsserá indefinido durante el constructor que puede prestarse a confusión.
Dan Abramov

2
¿Para lograr qué? Puede definir un controlador dentro del componente funcional y pasarlo. Será una función diferente en cada renderizado, por lo que si ha determinado con un generador de perfiles que le da problemas de rendimiento (¡y solo si realmente está seguro de esto!), Considere usar una clase en su lugar.
Dan Abramov el

1
@ me-me Sí, y si opta por JavaScript de última generación en Babel, debe declarar las propiedades en su clase como foo = () => {...}y luego hacer referencia en renderizar <button onClick={this.foo}...la única razón para incluir una función de flecha si usa babel de esta manera, IMO, es si desea capturar alguna variable que solo existe en el alcance del método render () (los eventos solo se pueden pasar y no se aplican).
aikeru

73

[[h / t a @ E.Sundin por vincular esto en un comentario]

La respuesta principal (funciones anónimas o enlace) funcionará, pero no es la más eficaz, ya que crea una copia del controlador de eventos para cada instancia generada por la map()función.

Esta es una explicación de la forma óptima de hacerlo desde ESLint-plugin-react :

Listas de artículos

Un caso de uso común de bind en render es cuando se renderiza una lista, para tener una devolución de llamada separada por elemento de la lista:

const List = props => (
      <ul>
        {props.items.map(item =>
          <li key={item.id} onClick={() => console.log(item.id)}>
            ...
          </li>
        )}
      </ul>
    );

En lugar de hacerlo de esta manera, arrastre la sección repetida a su propio componente:

const List = props => (
      <ul>
        {props.items.map(item =>
          <ListItem 
            key={item.id} 
            item={item} 
            onItemClick={props.onItemClick} // assume this is passed down to List
           />
        )}
      </ul>
    );


const ListItem = props => {
  const _onClick = () => {
    console.log(props.item.id);
  }
    return (
      <li onClick={_onClick}>
        ...
      </li>
    );

});

Esto acelerará el renderizado, ya que evita la necesidad de crear nuevas funciones (a través de llamadas de enlace) en cada render.


¿Reacciona invocar esas funciones con call / apply, entonces, bajo el capó, y evita usar bind internamente?
aikeru

1
¿Hay alguna manera de hacer esto usando un componente sin estado?
Carlos Martinez

2
@CarlosMartinez buen ojo, actualicé el ejemplo: deberían haber sido componentes funcionales sin estado (SFC) en primer lugar. En general, si un componente nunca se usa this.state, puede intercambiarlo con seguridad con un SFC.
Brandon

3
Hmm, no entiendo cómo esto es más eficiente? No se invocará la función ListItem cada vez y, por lo tanto, la función _onClick se creará en cada render.
Mattias Petter Johansson

1
Estoy lejos de ser un experto aquí, pero como lo entiendo, en el patrón 'correcto', solo hay una instancia del controlador y se le pasa el apoyo para cualquier instancia del componente que lo llame. En el ejemplo de enlace (es decir, el patrón 'incorrecto'), hay una instancia del controlador para cada componente instanciado. Es una especie de memoria equivalente a escribir la misma función treinta veces al escribirla una vez y llamarla cuando sea necesario.
Brandon

25

Este es mi enfoque, no estoy seguro de lo malo que es, por favor comente

En el elemento cliqueable

return (
    <th value={column} onClick={that.handleSort} data-column={column}>   {column}</th>
);

y entonces

handleSort(e){
    this.sortOn(e.currentTarget.getAttribute('data-column'));
}

Este es un enfoque en el que estaba pensando, se siente un poco hacky pero evita crear un nuevo componente. No estoy seguro de si getAttribute es mejor o peor en términos de rendimiento en comparación con la inserción en un componente separado.
kamranicus

2
Creo que es una buena solución porque es muy simple. Pero solo funciona con valores de cadena, si desea un objeto, no funciona.
Stephane L

Para que un objeto que tendría que hacer encodeURIComponent(JSON.stringify(myObj)), a continuación, analizarlo, JSON.parse(decodeURIComponent(myObj)). Para las funciones, estoy bastante seguro de que esto no funcionará sin eval o new Function (), que deben evitarse. Por estas razones, no uso atributos de datos para pasar datos en React / JS.
Solvitieg

Quiero agregar que no uso esto a menudo y solo para cosas menores. Pero generalmente solo creo un componente y le paso los datos como accesorios. Luego, maneje el clic dentro de ese nuevo componente o pase una función onClick al componente. Me gusta se explica en la respuesta de Brandon
Santiago Ramírez,

1
se puede acceder directamente al conjunto de datos de esta manera en los navegadores modernos (incluido IE11): e.currentTarget.dataset.column
gsziszi

17

Este ejemplo puede ser un poco diferente al suyo. pero puedo asegurarle que esta es la mejor solución que puede tener para este problema. He buscado durante días una solución que no tenga problemas de rendimiento. y finalmente se me ocurrió esta.

class HtmlComponent extends React.Component {
  constructor() {
    super();
    this.state={
       name:'MrRehman',
    };
    this.handleClick= this.handleClick.bind(this);
  }

  handleClick(event) {
    const { param } = e.target.dataset;
    console.log(param);
    //do what you want to do with the parameter
  }

  render() {
    return (
      <div>
        <h3 data-param="value what you wanted to pass" onClick={this.handleClick}>
          {this.state.name}
        </h3>
      </div>
    );
  }
}

ACTUALIZAR

en caso de que desee tratar con objetos que se supone que son los parámetros. puede usar JSON.stringify(object)para convertirlo en cadena y agregarlo al conjunto de datos.

return (
   <div>
     <h3 data-param={JSON.stringify({name:'me'})} onClick={this.handleClick}>
        {this.state.name}
     </h3>
   </div>
);

1
esto no funciona cuando los datos pasados ​​son un objeto
SlimSim

use JSON.stringify para solucionar el problema. @SlimSim. eso debería hacer el truco
hannad rehman

Si necesita usar JSON.stringify para este problema, entonces probablemente no sea el método correcto. El proceso de stringificación requiere mucha memoria.
KFE

en la mayoría de los casos, solo pasaría la ID como parámetros, y obtendría los detalles del objeto basados ​​en esa ID de su objeto fuente. y cómo y por qué se tarda una gran cantidad de memoria, sé JSON stringify es lento, pero el clic Fn es asíncrono y no tendrá ningún efecto sobre o 0 dom, una vez construidos
Rehman hannad

6
class extends React.Component {
    onClickDiv = (column) => {
        // do stuff
    }
    render() {
        return <div onClick={() => this.onClickDiv('123')} />
    }
}

2
Lo mismo: nuevo DOM en cada render. Entonces React actualizará DOM cada vez.
Alex Shwarc

4

Una opción más que no involucra .bindo ES6 es usar un componente hijo con un controlador para llamar al controlador principal con los accesorios necesarios. Aquí hay un ejemplo (y un enlace al ejemplo de trabajo está abajo)

var HeaderRows = React.createClass({
  handleSort:  function(value) {
     console.log(value);
  },
  render: function () {
      var that = this;
      return(
          <tr>
              {this.props.defaultColumns.map(function (column) {
                  return (
                      <TableHeader value={column} onClick={that.handleSort} >
                        {column}
                      </TableHeader>
                  );
              })}
              {this.props.externalColumns.map(function (column) {
                  // Multi dimension array - 0 is column name
                  var externalColumnName = column[0];
                  return ( <th>{externalColumnName}</th>
                  );
              })}
          </tr>);
      )
  }
});

// A child component to pass the props back to the parent handler
var TableHeader = React.createClass({
  propTypes: {
    value: React.PropTypes.string,
    onClick: React.PropTypes.func
  },
  render: function () {
    return (
      <th value={this.props.value} onClick={this._handleClick}
        {this.props.children}
      </th>
    )        
  },
  _handleClick: function () {
    if (this.props.onClick) {
      this.props.onClick(this.props.value);
    }
  }
});

La idea básica es que el componente padre pase la onClickfunción a un componente hijo. El componente secundario llama a la onClickfunción y puede acceder a todo lo que se le propspase (y al event), lo que le permite usar cualquier eventvalor u otros accesorios dentro de la onClickfunción del padre .

Aquí hay una demostración de CodePen que muestra este método en acción.


4

Hacer un intento alternativo para responder la pregunta de OP, incluidas las llamadas e.preventDefault ():

Enlace representado ( ES6 )

<a href="#link" onClick={(e) => this.handleSort(e, 'myParam')}>

Función componente

handleSort = (e, param) => {
  e.preventDefault();
  console.log('Sorting by: ' + param)
}

4

Me doy cuenta de que esto es bastante tarde para la fiesta, pero creo que una solución mucho más simple podría satisfacer muchos casos de uso:

    handleEdit(event) {
        let value = event.target.value;
    }

    ...

    <button
        value={post.id}
        onClick={this.handleEdit} >Edit</button>

Supongo que también podrías usar un data-atributo.

Sencillo, semántico.


4

Simplemente cree una función como esta

  function methodName(params) {
    //the thing  you wanna do
  }

y llámalo en el lugar que necesites

<Icon onClick = {() => {methodName (theParamsYouwantToPass); }} />


3

Simplemente puede hacerlo si está utilizando ES6.

export default class Container extends Component {
  state = {
    data: [
        // ...
    ]
  }

  handleItemChange = (e, data) => {
      // here the data is available 
      // ....
  }
  render () {
     return (
        <div>
        {
           this.state.data.map((item, index) => (
              <div key={index}>
                  <Input onChange={(event) => this.handItemChange(event, 
                         item)} value={item.value}/>
              </div>
           ))
        }
        </div>
     );
   }
 }

3

La implementación muestra el recuento total de un objeto pasando el recuento como parámetro de los componentes principales a los subcomponentes como se describe a continuación.

Aquí está MainComponent.js

import React, { Component } from "react";

import SubComp from "./subcomponent";

class App extends Component {

  getTotalCount = (count) => {
    this.setState({
      total: this.state.total + count
    })
  };

  state = {
    total: 0
  };

  render() {
    const someData = [
      { name: "one", count: 200 },
      { name: "two", count: 100 },
      { name: "three", count: 50 }
    ];
    return (
      <div className="App">
        {someData.map((nameAndCount, i) => {
          return (
            <SubComp
              getTotal={this.getTotalCount}
              name={nameAndCount.name}
              count={nameAndCount.count}
              key={i}
            />
          );
        })}
        <h1>Total Count: {this.state.total}</h1>
      </div>
    );
  }
}

export default App;

Y aqui esta SubComp.js

import React, { Component } from 'react';
export default class SubComp extends Component {

  calculateTotal = () =>{
    this.props.getTotal(this.props.count);
  }

  render() {
    return (
      <div>
        <p onClick={this.calculateTotal}> Name: {this.props.name} || Count: {this.props.count}</p>
      </div>
    )
  }
};

Intente implementar lo anterior y obtendrá un escenario exacto de cómo funcionan los parámetros de paso en reactjs en cualquier método DOM.


3

Escribí un componente contenedor que se puede reutilizar para este propósito que se basa en las respuestas aceptadas aquí. Sin embargo, si todo lo que necesita hacer es pasar una cadena, simplemente agregue un atributo de datos y léalo desde e.target.dataset (como han sugerido algunos otros). Por defecto, mi contenedor se unirá a cualquier accesorio que sea una función y comience con 'on' y automáticamente pasará el accesorio de datos al llamador después de todos los demás argumentos de evento. Aunque no lo he probado para el rendimiento, le dará la oportunidad de evitar crear la clase usted mismo, y se puede usar así:

const DataButton = withData('button')
const DataInput = withData('input');

o para componentes y funciones

const DataInput = withData(SomeComponent);

o si lo prefieres

const DataButton = withData(<button/>)

declarar que fuera de su contenedor (cerca de sus importaciones)

Aquí está el uso en un contenedor:

import withData from './withData';
const DataInput = withData('input');

export default class Container extends Component {
    state = {
         data: [
             // ...
         ]
    }

    handleItemChange = (e, data) => {
        // here the data is available 
        // ....
    }

    render () {
        return (
            <div>
                {
                    this.state.data.map((item, index) => (
                        <div key={index}>
                            <DataInput data={item} onChange={this.handleItemChange} value={item.value}/>
                        </div>
                    ))
                }
            </div>
        );
    }
}

Aquí está el código del contenedor 'withData.js:

import React, { Component } from 'react';

const defaultOptions = {
    events: undefined,
}

export default (Target, options) => {
    Target = React.isValidElement(Target) ? Target.type : Target;
    options = { ...defaultOptions, ...options }

    class WithData extends Component {
        constructor(props, context){
            super(props, context);
            this.handlers = getHandlers(options.events, this);        
        }

        render() {
            const { data, children, ...props } = this.props;
            return <Target {...props} {...this.handlers} >{children}</Target>;
        }

        static displayName = `withData(${Target.displayName || Target.name || 'Component'})`
    }

    return WithData;
}

function getHandlers(events, thisContext) {
    if(!events)
        events = Object.keys(thisContext.props).filter(prop => prop.startsWith('on') && typeof thisContext.props[prop] === 'function')
    else if (typeof events === 'string')
        events = [events];

    return events.reduce((result, eventType) => {
        result[eventType] = (...args) => thisContext.props[eventType](...args, thisContext.props.data);
        return result;
    }, {});
}

2

Tengo más de 3 sugerencias para esto en JSX onClick Events:

  1. En realidad, no necesitamos usar la función .bind () o Arrow en nuestro código. Puedes usarlo fácilmente en tu código.

  2. También puede mover el evento onClick de th (o ul) a tr (o li) para mejorar el rendimiento. Básicamente tendrá un número n de "Oyentes de eventos" para su elemento n li.

    So finally code will look like this:
    <ul onClick={this.onItemClick}>
        {this.props.items.map(item =>
               <li key={item.id} data-itemid={item.id}>
                   ...
               </li>
          )}
    </ul>

    // Y puedes acceder item.iden el onItemClickmétodo como se muestra a continuación:

    onItemClick = (event) => {
       console.log(e.target.getAttribute("item.id"));
    }
  3. Estoy de acuerdo con el enfoque mencionado anteriormente para crear un componente React separado para ListItem y List. Este código de marca se ve bien, sin embargo, si tiene 1000 de li, se crearán 1000 oyentes de eventos. Asegúrate de no tener mucho oyente de eventos.

    import React from "react";
    import ListItem from "./ListItem";
    export default class List extends React.Component {
    
        /**
        * This List react component is generic component which take props as list of items and also provide onlick
        * callback name handleItemClick
        * @param {String} item - item object passed to caller
        */
        handleItemClick = (item) => {
            if (this.props.onItemClick) {
                this.props.onItemClick(item);
            }
        }
    
        /**
        * render method will take list of items as a props and include ListItem component
        * @returns {string} - return the list of items
        */
        render() {
            return (
                <div>
                  {this.props.items.map(item =>
                      <ListItem key={item.id} item={item} onItemClick={this.handleItemClick}/>
                  )}
                </div>
            );
        }
    
    }
    
    
    import React from "react";
    
    export default class ListItem extends React.Component {
        /**
        * This List react component is generic component which take props as item and also provide onlick
        * callback name handleItemClick
        * @param {String} item - item object passed to caller
        */
        handleItemClick = () => {
            if (this.props.item && this.props.onItemClick) {
                this.props.onItemClick(this.props.item);
            }
        }
        /**
        * render method will take item as a props and print in li
        * @returns {string} - return the list of items
        */
        render() {
            return (
                <li key={this.props.item.id} onClick={this.handleItemClick}>{this.props.item.text}</li>
            );
        }
    }

1
Esto no funciona cuando los datos que necesita pasar son un objeto. El atributo solo funcionará con cadenas. También leer desde el dom a través del atributo get es probablemente una operación más costosa.
SlimSim

2

He agregado código para pasar el valor del evento onclick al método de dos maneras. 1) usando el método de enlace 2. usando el método de flecha (=>). ver los métodos handleort1 y handleort

var HeaderRows  = React.createClass({
    getInitialState : function() {
      return ({
        defaultColumns : ["col1","col2","col2","col3","col4","col5" ],
        externalColumns : ["ecol1","ecol2","ecol2","ecol3","ecol4","ecol5" ],

      })
    },
    handleSort:  function(column,that) {
       console.log(column);
       alert(""+JSON.stringify(column));
    },
    handleSort1:  function(column) {
       console.log(column);
       alert(""+JSON.stringify(column));
    },
    render: function () {
        var that = this;
        return(
        <div>
            <div>Using bind method</div>
            {this.state.defaultColumns.map(function (column) {
                return (
                    <div value={column} style={{height : '40' }}onClick={that.handleSort.bind(that,column)} >{column}</div>
                );
            })}
            <div>Using Arrow method</div>

            {this.state.defaultColumns.map(function (column) {
                return (
                    <div value={column} style={{height : 40}} onClick={() => that.handleSort1(column)} >{column}</div>

                );
            })}
            {this.state.externalColumns.map(function (column) {
                // Multi dimension array - 0 is column name
                var externalColumnName = column;
                return (<div><span>{externalColumnName}</span></div>
                );
            })}

        </div>);
    }
});

2

A continuación se muestra el ejemplo que pasa valor en el evento onClick.

Usé la sintaxis es6. recuerde que la función de flecha de componente de clase no se vincula automáticamente, por lo que se vincula explícitamente en el constructor.

class HeaderRows extends React.Component {

    constructor(props) {
        super(props);
        this.handleSort = this.handleSort.bind(this);
    }

    handleSort(value) {
        console.log(value);
    }

    render() {
        return(
            <tr>
                {this.props.defaultColumns.map( (column, index) =>
                    <th value={ column } 
                        key={ index } 
                        onClick={ () => this.handleSort(event.target.value) }>
                        { column }
                    </th>
                )}

                {this.props.externalColumns.map((column, index)  =>
                    <th value ={ column[0] }
                        key={ index }>
                        {column[0]}
                    </th>
                )}
            </tr>
         );
    }
}

2

Supongo que tendrás que vincular el método a la instancia de clase de React. Es más seguro usar un constructor para unir todos los métodos en React. En su caso, cuando pasa el parámetro al método, el primer parámetro se utiliza para vincular el contexto 'this' del método, por lo que no puede acceder al valor dentro del método.


2
1. You just have to use an arrow function in the Onclick event like this: 

<th value={column} onClick={() => that.handleSort(theValue)} >{column}</th>

2.Then bind this in the constructor method:
    this.handleSort = this.handleSort.bind(this);

3.And finally get the value in the function:
  handleSort(theValue){
     console.log(theValue);
}

2

Hay una manera muy fácil.

 onClick={this.toggleStart('xyz')} . 
  toggleStart= (data) => (e) =>{
     console.log('value is'+data);  
 }

2
class TableHeader extends Component {
  handleClick = (parameter,event) => {
console.log(parameter)
console.log(event)

  }

  render() {
    return (
      <button type="button" 
onClick={this.handleClick.bind(this,"dataOne")}>Send</button>
    );
  }
}

44
Si bien este código puede resolver la pregunta, incluir una explicación realmente ayuda a mejorar la calidad de su publicación. Recuerde que está respondiendo la pregunta para los lectores en el futuro, y que esas personas podrían no conocer los motivos de su sugerencia de código.
Shree

2

Saliendo de la nada a esta pregunta, pero creo .bindque funcionará. Encuentra el código de muestra a continuación.

const handleClick = (data) => {
    console.log(data)
}

<button onClick={handleClick.bind(null, { title: 'mytitle', id: '12345' })}>Login</button>

1

Usando la función de flecha:

Debe instalar la etapa 2:

npm install babel-preset-stage-2:

class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            value=0
        }
    }

    changeValue = (data) => (e) => {
        alert(data);  //10
        this.setState({ [value]: data })
    }

    render() {
        const data = 10;
        return (
            <div>
                <input type="button" onClick={this.changeValue(data)} />
            </div>
        );
    }
}
export default App; 

0

Hay 3 formas de manejar esto: -

  1. Enlace el método en constructor como: -

    export class HeaderRows extends Component {
       constructor() {
           super();
           this.handleSort = this.handleSort.bind(this);
       }
    }
  2. Use la función de flecha mientras la crea como: -

    handleSort = () => {
        // some text here
    }
  3. La tercera forma es esta: -

    <th value={column} onClick={() => that.handleSort} >{column}</th>

0

Puedes usar tu código así:

<th value={column} onClick={(e) => that.handleSort(e, column)} >{column}</th>

Aquí e es para objeto de evento, si desea utilizar métodos de evento como preventDefault()en su función de control o desea obtener un valor de destino o un nombre como e.target.name.


0

Encontré la solución de pasar el parámetro como atributo de una etiqueta bastante razonable.

Sin embargo tiene limitaciones:

  • No funciona correctamente cuando el elemento de la lista tiene otras etiquetas (por lo tanto, event.target puede ser diferente al previsto)
  • Param podría ser solo una cadena. Requiere serialización y deserialización.

Es por eso que se me ocurrió esta biblioteca: react-event-param

Eso:

  • Resuelve el problema de los niños buscando el atributo necesario en los padres cuando sea necesario
  • Serializa y deserializa automáticamente param
  • Encapsula la lógica de configuración y obtención. No es necesario meterse con los nombres de los parámetros

Ejemplo de uso:

import { setEventParam, getEventParam } from "react-event-param";

class List extends Component {
  onItemClick = e => {
    const index = getEventParam(e.target);
    // Do something with index
  };

  render() {
    return (
      <ul>
        {this.props.items.map((itemText, index) => (
          <li
            key={index}
            {...setEventParam(index)}
            onClick={this.onItemClick}
          >
            {{ itemText }}
          </li>
        ))}
      </ul>
    );
  }
}

export default List;

0

Hubo muchas consideraciones de rendimiento, todo en el vacío.
El problema con estos controladores es que debe curry para incorporar el argumento que no puede nombrar en los accesorios.
Esto significa que el componente necesita un controlador para cada elemento en el que se puede hacer clic. Acordemos que para algunos botones esto no es un problema, ¿verdad?
El problema surge cuando maneja datos tabulares con docenas de columnas y miles de filas. Ahí notas el impacto de crear tantos manejadores.

El hecho es que solo necesito uno.
Configuré el controlador en el nivel de la tabla (o UL u OL ...), y cuando ocurre el clic, puedo decir cuál fue la celda en la que se hizo clic utilizando los datos disponibles desde siempre en el objeto de evento:

nativeEvent.target.tagName
nativeEvent.target.parentElement.tagName 
nativeEvent.target.parentElement.rowIndex
nativeEvent.target.cellIndex
nativeEvent.target.textContent

Utilizo los campos de nombre de etiqueta para verificar que el clic se haya producido en un elemento válido, por ejemplo, ignore los clics en otros pies de página.
El rowIndex y cellIndex dan la ubicación exacta de la celda en la que se hizo clic.
El contenido de texto es el texto de la celda en la que se hizo clic.

De esta manera, no necesito pasar los datos de la celda al controlador, puede autoservicio.
Si necesitaba más datos, datos que no se mostrarán, puedo usar el atributo del conjunto de datos o elementos ocultos.
Con un poco de navegación DOM simple, todo está a la mano.
Esto se ha usado en HTML desde siempre, ya que las PC eran mucho más fáciles de empantanar.


0

Hay dos formas de pasar parámetros en controladores de eventos, algunas son las siguientes.

Puede usar una función de flecha para ajustar un controlador de eventos y pasar parámetros:

<button onClick={() => this.handleClick(id)} />

el ejemplo anterior es equivalente a llamar .bindo puede llamar explícitamente a bind.

<button onClick={this.handleClick.bind(this, id)} />

Además de estos dos enfoques, también puede pasar argumentos a una función que se define como una función de curry.

handleClick = (id) => () => {
    console.log("Hello, your ticket number is", id)
};

<button onClick={this.handleClick(id)} />

-1

Use un cierre , da como resultado una solución limpia:

<th onClick={this.handleSort(column)} >{column}</th>

La función handleSort devolverá una función que ya tiene la columna de valor establecida.

handleSort: function(value) { 
    return () => {
        console.log(value);
    }
}

La función anónima se llamará con el valor correcto cuando el usuario haga clic en el th.

Ejemplo: https://stackblitz.com/edit/react-pass-parameters-example


-2

Se requiere un cambio simple:

Utilizar <th value={column} onClick={that.handleSort} >{column}</th>

en vez de <th value={column} onClick={that.handleSort} >{column}</th>

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.