React js onClick no puede pasar valor al método

Resuelto user1924375 asked hace 9 años • 37 respuestas

Quiero leer las propiedades del valor del evento onClick. Pero cuando hago clic en él, veo algo como esto 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 verlo {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?

user1924375 avatar Apr 23 '15 06:04 user1924375
Aceptado

Camino fácil

Utilice 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

Extráigalo a un subcomponente. El problema con el uso de una función de flecha en la llamada de renderizado es que creará una nueva función cada vez, lo que termina provocando renderizados innecesarios.

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

Vieja manera fácil (ES5)

Úselo .bindpara pasar el parámetro que desee, de esta manera vinculará la función con el contexto del Componente:

return (
  <th value={column} onClick={this.handleSort.bind(this, column)}>{column}</th>
);
Austin Greco avatar Apr 22 '2015 23:04 Austin Greco

Hay buenas respuestas aquí y estoy de acuerdo con @Austin Greco (la segunda opción con componentes separados).
Hay otra forma que me gusta: el curry .
Lo que puedes hacer es crear una función que acepte un parámetro (tu parámetro) y devuelva otra función que acepte otro parámetro (el evento de clic en este caso). entonces eres libre de hacer con él 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)} 
/>

A continuación se muestra un ejemplo completo de dicho uso:

Mostrar fragmento de código

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

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:

Mostrar fragmento de código

Sagiv b.g avatar Aug 01 '2017 22:08 Sagiv b.g