OnClickイベント値のプロパティを読みたいです。しかし、それをクリックすると、コンソールに次のようなものが表示されます。
SyntheticMouseEvent {dispatchConfig: Object, dispatchMarker: ".1.1.0.2.0.0:1", nativeEvent: MouseEvent, type: "click", target
私のコードは正しく働いています。実行すると{column}
は表示されますがonClickイベントで取得できません。
私のコード:
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>);
}
});
React jsのonClick
イベントに値を渡すにはどうすればいいですか?
矢印機能を使う:
return (
<th value={column} onClick={() => this.handleSort(column)}>{column}</th>
);
これは正しいパラメータでhandleSort
を呼び出す新しい関数を作成します。
それをサブコンポーネントに展開します。 レンダーコールでarrow関数を使うことの問題は毎回新しい関数を作成することになります。不必要な再レンダリングを引き起こします。
サブコンポーネントを作成する場合は、handlerを渡して引数としてpropsを使用できます。これにより、propsが変更された場合にのみ再レンダリングされます(ハンドラ参照は変更されないため)。
サブコンポーネント
class TableHeader extends Component {
handleClick = () => {
this.props.onHeaderClick(this.props.value);
}
render() {
return (
<th onClick={this.handleClick}>
{this.props.column}
</th>
);
}
}
主成分
{this.props.defaultColumns.map((column) => (
<TableHeader
value={column}
onHeaderClick={this.handleSort}
/>
))}
オールドイージーウェイ(ES5)
必要なパラメータを渡すには、 .bind
を使用します。
return (
<th value={column} onClick={that.handleSort.bind(that, column)}>{column}</th>
);
今日、ES6では、最新の回答を使用できると思います。
return (
<th value={column} onClick={()=>this.handleSort(column)} >{column}</th>
);
基本的に、(知らない人のために)onClick
は渡された関数を期待しているので、bind
は関数のコピーを作成するので機能します。代わりに、欲しい関数を呼び出してthis
を保存する矢印関数式を渡すことができます。 Reactでrender
メソッドをバインドする必要はありませんが、何らかの理由でコンポーネントメソッドの1つでthis
を失う場合は、
constructor(props) {
super(props);
this.myMethod = this.myMethod.bind(this);
}
ここにいい答えがあります、そして私は@Austin Grecoに同意します(別々のコンポーネントを持つ2番目のオプション)
私が好むもう一つの方法は、 カレー です。
できることは、パラメータを受け取る関数(自分のパラメータ)を作成し、別のパラメータ(この場合はclickイベント)を受け取る別の関数を返すことです。それならあなたは今まであなたが望んでいたことを自由に行うことができます。
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
};
そして、あなたはこのようにそれを使うでしょう:
<input
type="text"
onChange={this.handleChange(someParam)}
/>
これがそのような使い方の完全な例です:
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>
この方法では、各レンダリングでの新しいインスタンスの作成は解決されません。
私の意見では、これはより簡潔で読みやすいので、他のインラインハンドラーよりもこのアプローチが好きです。
編集:
以下のコメントで示唆されているように、関数の結果をキャッシュ/記憶することができます。
これは単純な実装です。
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" />
[[h/tから@ E.Sundinへ コメント内のthis へのリンク]
一番上の答え(匿名関数または束縛)は機能しますが、map()
関数によって生成されたすべてのインスタンスに対してイベントハンドラーのコピーを作成するので、それは最も高性能なものではありません。
これは ESLint-plugin-react から実行するのに最適な方法の説明です。
商品リスト
Renderにおけるbindの一般的なユースケースは、リストをレンダリングするとき、リストアイテムごとに別々のコールバックを持つことです。
const List = props => (
<ul>
{props.items.map(item =>
<li key={item.id} onClick={() => console.log(item.id)}>
...
</li>
)}
</ul>
);
このようにするのではなく、繰り返されるセクションを独自のコンポーネントにプルします。
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>
);
});
これにより、レンダリングごとに(バインド呼び出しを通じて)新しい関数を作成する必要がなくなるため、レンダリングが高速化されます。
これは私のアプローチです、それがどれほど悪いかわからない、コメントしてください
クリック可能な要素内
return (
<th value={column} onClick={that.handleSort} data-column={column}> {column}</th>
);
その後
handleSort(e){
this.sortOn(e.currentTarget.getAttribute('data-column'));
}
この例はあなたのものとは少し違うかもしれません。しかし、私はこれがあなたがこの問題に対して持つことができる最善の解決策であることをあなたに保証することができます。パフォーマンスの問題がない解決策を何日もかけて探しました。そしてついにこれを思いついた。
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
パラメータとなるはずのオブジェクトを扱いたい場合。 JSON.stringify(object)
を使って文字列に変換し、データセットに追加することができます。
return (
<div>
<h3 data-param={JSON.stringify({name:'me'})} onClick={this.handleClick}>
{this.state.name}
</h3>
</div>
);
.bind
またはES6を含まないもう1つのオプションは、必要な小道具を使って親ハンドラーを呼び出すためにハンドラーを持つ子コンポーネントを使用することです。これが例です(そして、実例へのリンクは以下です):
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);
}
}
});
基本的な考え方は、親コンポーネントがonClick
関数を子コンポーネントに渡すことです。子コンポーネントはonClick
関数を呼び出し、それに渡された任意のprops
(およびevent
)にアクセスできます。これにより、親のevent
関数内で任意のonClick
値または他の小道具を使用できます。
これが CodePenデモ です。
class extends React.Component {
onClickDiv = (column) => {
// do stuff
}
render() {
return <div onClick={() => this.onClickDiv('123')} />
}
}
私はこれが当事者にはかなり遅いと認識していますが、もっと簡単な解決策が多くのユースケースを満たすことができると思います。
handleEdit(event) {
let value = event.target.value;
}
...
<button
value={post.id}
onClick={this.handleEdit} >Edit</button>
data-
属性も使えると思います。
シンプル、意味的.
以下で説明するように、メインコンポーネントからサブコンポーネントへのパラメータとしてcountを渡すことで、オブジェクトからのshow total countを実装します。
これが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;
そしてこれが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>
)
}
};
上記を実装してみてください。そうすれば、どのDOMメソッドの場合でもpassパラメータがreactjsでどのように機能するかという正確なシナリオがわかります。
Onclickイベントの値をメソッドに渡すためのコードを2つの方法で追加しました。 1。 bindメソッドを使う2. arrow(=>)メソッドを使うhandleort1メソッドと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>);
}
});
私はこの目的のために再利用できるラッパーコンポーネントを書きました。ただし、文字列を渡すだけでよい場合は、data-attributeを追加し、それをe.target.datasetから読み取るだけです(他の人が提案したように)。デフォルトでは、私のラッパーは関数であるすべてのプロップにバインドし、 'on'で始まり、他のすべてのイベント引数の後に自動的にデータプロップを呼び出し元に返します。パフォーマンスについてはテストしていませんが、自分でクラスを作成しないようにすることができます。このように使用できます。
const DataButton = withData('button')
const DataInput = withData('input');
またはコンポーネントと機能
const DataInput = withData(SomeComponent);
またはあなたが好めば
const DataButton = withData(<button/>)
あなたのコンテナの外側(輸入の近く)にそれを宣言する
これがコンテナでの使い方です。
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>
);
}
}
これがラッパーコード '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;
}, {});
}
これはとても簡単な方法です。
onClick={this.toggleStart('xyz')} .
toggleStart= (data) => (e) =>{
console.log('value is'+data);
}
E.preventDefault()呼び出しを含む、OPの質問に答えるための別の試みをする:
レンダリングされたリンク(ES6)
<a href="#link" onClick={(e) => this.handleSort(e, 'myParam')}>
コンポーネント機能
handleSort = (e, param) => {
e.preventDefault();
console.log('Sorting by: ' + param)
}
私はJSX onClickイベントでこれについて3つ以下の提案をしています -
実際には、コード内で.bind()やArrow関数を使用する必要はありません。あなたのコードで簡単に使用することができます。
パフォーマンスを向上させるために、onClickイベントをth(またはul)からtr(またはli)に移動することもできます。基本的に、n li要素にはn個の "Event Listeners"があります。
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>
//そして、以下に示すようにonItemClick
メソッドでitem.id
にアクセスできます。
onItemClick = (event) => {
console.log(e.target.getAttribute("item.id"));
}
ListItemとListに対して別々のReactコンポーネントを作成するための上記のアプローチに同意します。ただし、このmakeコードは、1000個のliがある場合は1000個のEvent Listenersが作成されます。たくさんのイベントリスナーを持たないようにしてください。
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>
);
}
}
以下はonClickイベントに値を渡す例です。
私はes6構文を使いました。クラスコンポーネントの中で覚えておいてください矢印関数は自動的にバインドされないので、コンストラクタで明示的にバインドします。
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をインストールする必要があります。
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;
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>
);
}
}
あなたが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>
);
}
}
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);
}
メソッドをReactのクラスインスタンスにバインドする必要があると思います。 Reactのすべてのメソッドをバインドするためにコンストラクタを使用する方が安全です。あなたのケースでは、メソッドにパラメータを渡すとき、最初のパラメータはメソッドの 'this'コンテキストをバインドするために使われるので、メソッド内の値にアクセスすることはできません。
あなたはこのようにあなたのコードを使うことができます:
<th value={column} onClick={(e) => that.handleSort(e, column)} >{column}</th>
ハンドル関数でpreventDefault()
のようなイベントメソッドを使用したい場合、またはe.target.name
のようなターゲット値または名前を取得したい場合は、eはイベントオブジェクト用です。
これを処理する3つの方法があります: -
次のようにコンストラクタ内でメソッドをバインドします -
export class HeaderRows extends Component {
constructor() {
super();
this.handleSort = this.handleSort.bind(this);
}
}
としてそれを作成しながら矢印関数を使用します -
handleSort = () => {
// some text here
}
第三の方法はこれです: -
<th value={column} onClick={() => that.handleSort} >{column}</th>
私は、タグの属性としてparamを渡すという解決策が非常に合理的であることを見つけました。
しかしそれには限界があります。
私がこのライブラリを思いついたのはこのためです。 https://github.com/sneas/react-event-param
それ:
使用例
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;