Ich möchte die onClick-Ereigniswerteigenschaften lesen. Aber wenn ich darauf klicke, sehe ich so etwas auf der Konsole:
SyntheticMouseEvent {dispatchConfig: Object, dispatchMarker: ".1.1.0.2.0.0:1", nativeEvent: MouseEvent, type: "click", target
Mein Code funktioniert korrekt. Wenn ich renne, sehe ich {column}
, kann es aber nicht im onClick-Ereignis abrufen.
Mein Code:
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>);
}
});
Wie kann ich dem Ereignis onClick
in React js einen Wert übergeben?
Verwenden Sie eine Pfeilfunktion:
_return (
<th value={column} onClick={() => this.handleSort(column)}>{column}</th>
);
_
Dadurch wird eine neue Funktion erstellt, die handleSort
mit den richtigen Parametern aufruft.
Extrahieren Sie es in eine Unterkomponente. Das Problem bei der Verwendung einer Pfeilfunktion im Renderaufruf besteht darin, dass jedes Mal eine neue Funktion erstellt wird, die zu nicht benötigten erneuten Rendern führt.
Wenn Sie eine Unterkomponente erstellen, können Sie den Handler übergeben und Requisiten als Argumente verwenden. Diese werden dann nur dann neu gerendert, wenn sich die Requisiten ändern (da sich die Handlerreferenz jetzt nie ändert):
Unterkomponente
_class TableHeader extends Component {
handleClick = () => {
this.props.onHeaderClick(this.props.value);
}
render() {
return (
<th onClick={this.handleClick}>
{this.props.column}
</th>
);
}
}
_
Hauptkomponente
_{this.props.defaultColumns.map((column) => (
<TableHeader
value={column}
onHeaderClick={this.handleSort}
/>
))}
_
Old Easy Way (ES5)
Verwenden Sie .bind
, um den gewünschten Parameter zu übergeben:
_return (
<th value={column} onClick={that.handleSort.bind(that, column)}>{column}</th>
);
_
Hier gibt es nette Antworten und ich stimme @Austin Greco zu (die zweite Option mit separaten Komponenten)
Es gibt einen anderen Weg, den ich mag, Curry .
Sie können eine Funktion erstellen, die einen Parameter (Ihren Parameter) akzeptiert und eine andere Funktion zurückgibt, die einen anderen Parameter akzeptiert (in diesem Fall das Ereignis click). dann kannst du damit machen, was immer du willst.
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
};
Und du wirst es so benutzen:
<input
type="text"
onChange={this.handleChange(someParam)}
/>
Hier ist ein vollständiges Beispiel für eine solche Verwendung:
const someArr = ["A", "B", "C", "D"];
class App extends React.Component {
state = {
valueA: "",
valueB: "some initial value",
valueC: "",
valueD: "blah blah"
};
handleChange = param => e => {
const nextValue = e.target.value;
this.setState({ ["value" + param]: nextValue });
};
render() {
return (
<div>
{someArr.map(obj => {
return (
<div>
<label>
{`input ${obj} `}
</label>
<input
type="text"
value={this.state["value" + obj]}
onChange={this.handleChange(obj)}
/>
<br />
<br />
</div>
);
})}
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
Beachten Sie, dass dieser Ansatz nicht die Erstellung einer neuen Instanz bei jedem Rendern löst.
Ich mag diesen Ansatz gegenüber den anderen Inline-Handlern, da dieser meiner Meinung nach prägnanter und lesbarer ist.
Bearbeiten:
Wie in den Kommentaren unten vorgeschlagen, können Sie das Ergebnis der Funktion zwischenspeichern/speichern.
Hier ist eine naive Implementierung:
let memo = {};
const someArr = ["A", "B", "C", "D"];
class App extends React.Component {
state = {
valueA: "",
valueB: "some initial value",
valueC: "",
valueD: "blah blah"
};
handleChange = param => {
const handler = e => {
const nextValue = e.target.value;
this.setState({ ["value" + param]: nextValue });
}
if (!memo[param]) {
memo[param] = e => handler(e)
}
return memo[param]
};
render() {
return (
<div>
{someArr.map(obj => {
return (
<div key={obj}>
<label>
{`input ${obj} `}
</label>
<input
type="text"
value={this.state["value" + obj]}
onChange={this.handleChange(obj)}
/>
<br />
<br />
</div>
);
})}
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root" />
Heutzutage denke ich, dass wir mit ES6 eine aktualisierte Antwort gebrauchen könnten.
return (
<th value={column} onClick={()=>this.handleSort(column)} >{column}</th>
);
Grundsätzlich funktioniert onClick
(für alle, die es nicht wissen), da bind
eine an ihn übergebene Funktion erwartet, da eine Kopie einer Funktion erstellt wird. Stattdessen können wir einen Pfeilfunktionsausdruck übergeben, der einfach die gewünschte Funktion aufruft und this
beibehält. Sie sollten niemals die Methode render
in React binden müssen, aber wenn Sie aus irgendeinem Grund this
in einer Ihrer Komponentenmethoden verlieren:
constructor(props) {
super(props);
this.myMethod = this.myMethod.bind(this);
}
[[h/t an @ E.Sundin für Verknüpfung in einem Kommentar]
Die Top-Antwort (anonyme Funktionen oder Bindung) funktioniert, ist jedoch nicht die performanteste, da für jede Instanz, die von der Funktion map()
generiert wird, eine Kopie des Event-Handlers erstellt wird.
Dies ist eine Erklärung für die optimale Vorgehensweise aus dem ESLint-Plugin-Reagieren :
Listen von Gegenständen
Ein häufiger Anwendungsfall für das Binden beim Rendern ist das Rendern einer Liste, um einen separaten Rückruf pro Listenelement zu erhalten:
const List = props => (
<ul>
{props.items.map(item =>
<li key={item.id} onClick={() => console.log(item.id)}>
...
</li>
)}
</ul>
);
Ziehen Sie den wiederholten Abschnitt nicht auf diese Weise, sondern in eine eigene Komponente:
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>
);
});
Dies beschleunigt das Rendern, da keine neuen Funktionen (durch Bindeaufrufe) bei jedem Rendern erstellt werden müssen.
Dies ist mein Ansatz, nicht sicher, wie schlimm es ist, bitte kommentieren
Im anklickbaren Element
return (
<th value={column} onClick={that.handleSort} data-column={column}> {column}</th>
);
und dann
handleSort(e){
this.sortOn(e.currentTarget.getAttribute('data-column'));
}
dieses Beispiel unterscheidet sich möglicherweise geringfügig von Ihrem. Aber ich kann Ihnen versichern, dass dies die beste Lösung für dieses Problem ist. Ich habe seit Tagen nach einer Lösung gesucht, die keine Leistungsprobleme hat. und kam schließlich mit diesem ein.
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>
);
}
}
UPDATE
in dem Fall, dass Sie sich mit Objekten befassen möchten, die als Parameter dienen sollen. Sie können JSON.stringify(object)
verwenden, um es in einen String umzuwandeln und dem Datensatz hinzuzufügen.
return (
<div>
<h3 data-param={JSON.stringify({name:'me'})} onClick={this.handleClick}>
{this.state.name}
</h3>
</div>
);
class extends React.Component {
onClickDiv = (column) => {
// do stuff
}
render() {
return <div onClick={() => this.onClickDiv('123')} />
}
}
Eine weitere Option, die .bind
oder ES6 nicht betrifft, besteht darin, eine untergeordnete Komponente mit einem Handler zu verwenden, um den übergeordneten Handler mit den erforderlichen Requisiten aufzurufen. Hier ist ein Beispiel (und ein Link zum Arbeitsbeispiel ist unten):
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);
}
}
});
Die Grundidee ist, dass die übergeordnete Komponente die Funktion onClick
an eine untergeordnete Komponente übergibt. Die untergeordnete Komponente ruft die Funktion onClick
auf und kann auf alle ihr übergebenen props
(und die event
) zugreifen, sodass Sie einen beliebigen event
-Wert oder andere Requisiten innerhalb der übergeordneten Funktion verwenden können onClick
Funktion.
Hier ist eine CodePen-Demo , die diese Methode in Aktion zeigt.
Mir ist klar, dass dies für die Party ziemlich spät ist, aber ich denke, eine viel einfachere Lösung könnte viele Anwendungsfälle befriedigen:
handleEdit(event) {
let value = event.target.value;
}
...
<button
value={post.id}
onClick={this.handleEdit} >Edit</button>
Ich nehme an, Sie könnten auch ein data-
-Attribut verwenden.
Einfach, semantisch.
Das Implementieren von show total count von einem Objekt durch Übergeben von count als Parameter von Haupt- zu Unterkomponenten, wie unten beschrieben.
Hier ist 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;
Und hier ist 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>
)
}
};
Versuchen Sie es oben zu implementieren, und Sie erhalten ein genaues Szenario, wie Übergabeparameter in reactjs auf jeder DOM-Methode funktionieren.
Ich habe der Methode auf zwei Arten Code für die Übergabe von onclick-Ereigniswerten hinzugefügt. 1. Verwenden der Bindungsmethode 2. Verwenden der Pfeilmethode (=>). Siehe die Methoden Handlesort1 und Handlesort
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>);
}
});
Ich habe eine Wrapper-Komponente geschrieben, die für diesen Zweck wiederverwendet werden kann und die auf den hier akzeptierten Antworten aufbaut. Wenn Sie jedoch nur einen String übergeben müssen, fügen Sie einfach ein Datenattribut hinzu und lesen Sie es aus e.target.dataset (wie einige andere vorgeschlagen haben). Standardmäßig bindet mein Wrapper an jede Requisite, die eine Funktion ist, und beginnt mit "Ein". Nach allen anderen Ereignisargumenten wird die Requisite automatisch an den Aufrufer zurückgegeben. Obwohl ich es nicht auf Leistung getestet habe, gibt es Ihnen die Möglichkeit, das Erstellen der Klasse selbst zu vermeiden, und es kann folgendermaßen verwendet werden:
const DataButton = withData('button')
const DataInput = withData('input');
oder für Komponenten und Funktionen
const DataInput = withData(SomeComponent);
oder wenn Sie es vorziehen
const DataButton = withData(<button/>)
erklären, dass Außerhalb Ihres Containers (in der Nähe Ihrer Importe)
Hier ist die Verwendung in einem Container:
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>
);
}
}
Hier ist der Wrapper-Code '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;
}, {});
}
Theres ein sehr einfacher Weg.
onClick={this.toggleStart('xyz')} .
toggleStart= (data) => (e) =>{
console.log('value is'+data);
}
Machen Sie einen alternativen Versuch, die Frage von OP zu beantworten, einschließlich der Aufrufe von e.preventDefault ():
Gerenderter Link (ES6)
<a href="#link" onClick={(e) => this.handleSort(e, 'myParam')}>
Komponente Funktion
handleSort = (e, param) => {
e.preventDefault();
console.log('Sorting by: ' + param)
}
Ich habe unten 3 Vorschläge dazu bei JSX onClick Events -
Tatsächlich müssen wir in unserem Code nicht die Funktion .bind () oder Arrow verwenden. Sie können einfach in Ihrem Code verwenden.
Sie können das Ereignis onClick auch von th (oder ul) nach tr (oder li) verschieben, um die Leistung zu verbessern. Grundsätzlich haben Sie n Anzahl von "Event Listenern" für Ihr n li -Element.
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>
// Und Sie können auf item.id
in onItemClick
zugreifen, wie unten gezeigt:
onItemClick = (event) => {
console.log(e.target.getAttribute("item.id"));
}
Ich stimme dem oben erwähnten Ansatz zum Erstellen einer separaten React -Komponente für ListItem und List zu. Dieser Make-Code sieht jedoch gut aus, wenn Sie über 1000 li verfügen, werden 1000 Ereignis-Listener erstellt. Bitte stellen Sie sicher, dass Sie nicht viel Ereignis-Listener haben sollten.
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>
);
}
}
Das folgende Beispiel übergibt den Wert des onClick-Ereignisses.
Ich habe ES6-Syntax verwendet. Denken Sie daran, dass die Pfeilfunktion in der Klassenkomponente nicht automatisch gebunden wird. Daher wird sie im Konstruktor explizit gebunden.
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>
);
}
}
Mit pfeil funktion:
Sie müssen Stage-2 installieren:
npm installiere 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;
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>
);
}
}
Sie können es einfach tun, wenn Sie ES6
verwenden.
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>
);
}
}
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);
}
Ich vermute, Sie müssen die Methode an die Klasseninstanz von React binden. Es ist sicherer, einen Konstruktor zu verwenden, um alle Methoden in React zu binden. Wenn Sie den Parameter an die Methode übergeben, wird der erste Parameter verwendet, um den "this" -Kontext der Methode zu binden, sodass Sie nicht auf den Wert innerhalb der Methode zugreifen können.
Sie können Ihren Code folgendermaßen verwenden:
<th value={column} onClick={(e) => that.handleSort(e, column)} >{column}</th>
Hier ist e für ein Ereignisobjekt, wenn Sie Ereignismethoden wie preventDefault()
in Ihrer Handle-Funktion verwenden oder einen Zielwert oder Namen wie e.target.name
erhalten möchten.
Es gibt 3 Möglichkeiten, damit umzugehen:
Binden Sie die Methode im Konstruktor wie folgt:
export class HeaderRows extends Component {
constructor() {
super();
this.handleSort = this.handleSort.bind(this);
}
}
Verwenden Sie die Pfeilfunktion beim Erstellen als: -
handleSort = () => {
// some text here
}
Der dritte Weg ist:
<th value={column} onClick={() => that.handleSort} >{column}</th>
Ich fand die Lösung, param als Attribut eines Tags zu übergeben, ziemlich vernünftig.
Es hat jedoch Einschränkungen:
Deshalb habe ich mir diese Bibliothek ausgedacht: react-event-param
Es:
Anwendungsbeispiel:
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;