Javascript React js onClick 无法将值传递给方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/29810914/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
React js onClick can't pass value to method
提问by user1924375
I want to read the onClick event value properties. But when I click on it, I see something like this on the console:
我想读取 onClick 事件值属性。但是当我点击它时,我在控制台上看到了这样的东西:
SyntheticMouseEvent {dispatchConfig: Object, dispatchMarker: ".1.1.0.2.0.0:1", nativeEvent: MouseEvent, type: "click", target
My code is working correctly. When I run I can see {column}but can't get it in the onClick event.
我的代码工作正常。当我运行时,我可以看到{column}但无法在 onClick 事件中获取它。
My 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>
);
}
});
How can I pass a value to the onClickevent in React js?
如何将值传递给onClickReact js 中的事件?
回答by Austin Greco
Easy Way
简单的方法
Use an arrow function:
使用箭头函数:
return (
<th value={column} onClick={() => this.handleSort(column)}>{column}</th>
);
This will create a new function that calls handleSortwith the right params.
这将创建一个handleSort使用正确参数调用的新函数。
Better Way
更好的方法
Extract it into a sub-component.The problem with using an arrow function in the render call is it will create a new function every time, which ends up causing unneeded re-renders.
将其提取到子组件中。在渲染调用中使用箭头函数的问题是它每次都会创建一个新函数,最终导致不必要的重新渲染。
If you create a sub-component, you can pass handler and use props as the arguments, which will then re-render only when the props change (because the handler reference now never changes):
如果你创建了一个子组件,你可以传递 handler 并使用 props 作为参数,然后只有当 props 改变时才会重新渲染(因为处理程序引用现在永远不会改变):
Sub-component
子组件
class TableHeader extends Component {
handleClick = () => {
this.props.onHeaderClick(this.props.value);
}
render() {
return (
<th onClick={this.handleClick}>
{this.props.column}
</th>
);
}
}
Main component
主要成分
{this.props.defaultColumns.map((column) => (
<TableHeader
value={column}
onHeaderClick={this.handleSort}
/>
))}
Old Easy Way (ES5)
旧的简单方式 (ES5)
Use .bindto pass the parameter you want:
使用.bind通过所需要的参数:
return (
<th value={column} onClick={that.handleSort.bind(that, column)}>{column}</th>
);
回答by Sagiv b.g
There are nice answers here, and i agree with @Austin Greco (the second option with separate components)
There is another way i like, currying.
What you can do is create a function that accept a parameter (your parameter) and returns another function that accepts another parameter (the click event in this case). then you are free to do with it what ever you want.
这里有很好的答案,我同意@Austin Greco(带有单独组件的第二个选项)
还有另一种我喜欢的方式,currying。
您可以做的是创建一个函数,该函数接受一个参数(您的参数)并返回另一个接受另一个参数的函数(在本例中为 click 事件)。那么你就可以随意使用它。
ES5:
ES5:
handleChange(param) { // param is the argument you passed to the function
return function (e) { // e is the event object that returned
};
}
ES6:
ES6:
handleChange = param => e => {
// param is the argument you passed to the function
// e is the event object that returned
};
And you will use it this way:
你会这样使用它:
<input
type="text"
onChange={this.handleChange(someParam)}
/>
Here is a full example of such usage:
这是此类用法的完整示例:
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>
Note that this approach doesn't solve the creation of a new instance on each render.
I like this approach over the other inline handlers as this one is more concise and readable in my opinion.
请注意,此方法无法解决在每次渲染时创建新实例的问题。
与其他内联处理程序相比,我更喜欢这种方法,因为在我看来,这种方法更简洁易读。
Edit:
As suggested in the comments below, you can cache / memoize the result of the function.
编辑:
正如下面评论中所建议的,您可以缓存/记忆函数的结果。
Here is a naive implementation:
这是一个简单的实现:
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" />
回答by aikeru
Nowadays, with ES6, I feel we could use an updated answer.
如今,有了 ES6,我觉得我们可以使用更新的答案。
return (
<th value={column} onClick={()=>this.handleSort(column)} >{column}</th>
);
Basically, (for any that don't know) since onClickis expecting a function passed to it, bindworks because it creates a copy of a function. Instead we can pass an arrow function expression that simply invokes the function we want, and preserves this. You should never need to bind the rendermethod in React, but if for some reason you're losing thisin one of your component methods:
基本上,(对于任何不知道的人)因为onClick期望传递给它的函数,bind因为它创建了一个函数的副本。相反,我们可以传递一个箭头函数表达式,它简单地调用我们想要的函数,并保留this. 你永远不需要render在 React 中绑定方法,但是如果由于某种原因你丢失this了你的组件方法之一:
constructor(props) {
super(props);
this.myMethod = this.myMethod.bind(this);
}
回答by Brandon
[[h/t to @E.Sundin for linking thisin a comment]
[[h/t to @E.Sundin在评论中链接]
The top answer (anonymous functions or binding) will work, but it's not the most performant, as it creates a copy of the event handler for every instance generated by the map()function.
最佳答案(匿名函数或绑定)会起作用,但它并不是最高效的,因为它会为函数生成的每个实例创建事件处理程序的副本map()。
This is an explanation of the optimal way to do it from the ESLint-plugin-react:
这是从ESLint-plugin-react执行此操作的最佳方法的解释:
Lists of Items
A common use case of bind in render is when rendering a list, to have a separate callback per list item:
物品清单
在渲染中绑定的一个常见用例是在渲染列表时,每个列表项都有一个单独的回调:
const List = props => (
<ul>
{props.items.map(item =>
<li key={item.id} onClick={() => console.log(item.id)}>
...
</li>
)}
</ul>
);
Rather than doing it this way, pull the repeated section into its own component:
与其这样做,不如将重复的部分拉入其自己的组件中:
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>
);
});
This will speed up rendering, as it avoids the need to create new functions (through bind calls) on every render.
这将加速渲染,因为它避免了在每次渲染时创建新函数(通过绑定调用)的需要。
回答by Santiago Ramirez
This is my approach, not sure how bad it is, please comment
这是我的方法,不确定它有多糟糕,请评论
In the clickable element
在可点击元素中
return (
<th value={column} onClick={that.handleSort} data-column={column}> {column}</th>
);
and then
进而
handleSort(e){
this.sortOn(e.currentTarget.getAttribute('data-column'));
}
回答by hannad rehman
this example might be little different from yours. but i can assure you that this is the best solution you can have for this problem. i have searched for days for a solution which has no performance issue. and finally came up with this one.
这个例子可能与你的略有不同。但我可以向您保证,这是您可以针对此问题提供的最佳解决方案。我已经搜索了几天没有性能问题的解决方案。最后想出了这个。
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
更新
incase you want to deal with objects that are supposed to be the parameters. you can use JSON.stringify(object)to convert to it to string and add to the data set.
如果您想处理应该是参数的对象。您可以使用JSON.stringify(object)将其转换为字符串并添加到数据集。
return (
<div>
<h3 data-param={JSON.stringify({name:'me'})} onClick={this.handleClick}>
{this.state.name}
</h3>
</div>
);
回答by Vladimirs Matusevics
class extends React.Component {
onClickDiv = (column) => {
// do stuff
}
render() {
return <div onClick={() => this.onClickDiv('123')} />
}
}
回答by Brett DeWoody
One more option not involving .bindor ES6 is to use a child component with a handler to call the parent handler with the necessary props. Here's an example (and a link to working example is below):
.bind另一种不涉及ES6 的选项是使用带有处理程序的子组件来调用具有必要道具的父处理程序。这是一个示例(下面是工作示例的链接):
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);
}
}
});
The basic idea is for the parent component to pass the onClickfunction to a child component. The child component calls the onClickfunction and can access any propspassed to it (and the event), allowing you to use any eventvalue or other props within the parent's onClickfunction.
基本思想是让父组件将onClick函数传递给子组件。子组件调用该onClick函数并可以访问任何props传递给它的(和event),允许您event在父onClick函数中使用任何值或其他道具。
Here's a CodePen demoshowing this method in action.
这是一个CodePen 演示,展示了此方法的实际应用。
回答by Charith Jayasanka
Simply create a function like this
简单地创建一个这样的函数
function methodName(params) {
//the thing you wanna do
}
and call it in the place you need
并在您需要的地方调用它
< Icon onClick = { () => { methodName(theParamsYouwantToPass); } }/ >
< Icon onClick = { () => { methodName(theParamsYouwantToPass); } }/ >
回答by jhchnc
I realize this is pretty late to the party, but I think a much simpler solution could satisfy many use cases:
我意识到这对派对来说已经很晚了,但我认为一个更简单的解决方案可以满足许多用例:
handleEdit(event) {
let value = event.target.value;
}
...
<button
value={post.id}
onClick={this.handleEdit} >Edit</button>
I presume you could also use a data-attribute.
我想你也可以使用一个data-属性。
Simple, semantic.
简单,语义。

