React js onClick无法将值传递给方法

我想阅读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>
    );
  }
});

如何onClick在React js中将值传递给事件?

泡芙十三2020/03/09 22:45:49

You just need to use Arrow function to pass value.

<button onClick={() => this.props.onClickHandle("StackOverFlow")}>

Make sure to use () = >, Otherwise click method will be called without click event.

Note : Crash checks default methods

Please find below running code in codesandbox for the same.

React pass value with method

Stafan路易2020/03/09 22:45:49

Simple changed is required:

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

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

神无宝儿达蒙2020/03/09 22:45:48

There is a couple of ways to pass parameter in event handlers, some are following.

You can use an arrow function to wrap around an event handler and pass parameters:

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

above example is equivalent to calling .bind or you can explicitly call bind.

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

Apart from these two approaches, you can also pass arguments to a function which is defined as a curry function.

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

<button onClick={this.handleClick(id)} />
ProJinJin2020/03/09 22:45:48

There are 3 ways to handle this :-

  1. Bind the method in constructor as :-

    export class HeaderRows extends Component {
       constructor() {
           super();
           this.handleSort = this.handleSort.bind(this);
       }
    }
    
  2. Use the arrow function while creating it as :-

    handleSort = () => {
        // some text here
    }
    
  3. Third way is this :-

    <th value={column} onClick={() => that.handleSort} >{column}</th>
    
Sam猿泡芙2020/03/09 22:45:48

You can use your code like this:

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

Here e is for event object, if you want to use event methods like preventDefault() in your handle function or want to get target value or name like e.target.name.

A十三2020/03/09 22:45:48
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>
    );
  }
}
逆天LEY逆天2020/03/09 22:45:48

Using arrow function :

You must install stage-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; 
小小小胖2020/03/09 22:45:48
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);
}
Itachi小卤蛋凯2020/03/09 22:45:48

I guess you will have to bind the method to the React’s class instance. It’s safer to use a constructor to bind all methods in React. In your case when you pass the parameter to the method, the first parameter is used to bind the ‘this’ context of the method, thus you cannot access the value inside the method.

小小村村2020/03/09 22:45:48

Below is the example which passes value on onClick event.

I used es6 syntax. remember in class component arrow function does not bind automatically, so explicitly binding in 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>
         );
    }
}
西门Sam2020/03/09 22:45:47

You can simply do it if you are using 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>
     );
   }
 }
文韬武略辛弃疾2020/03/09 22:45:47

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

路易Itachi小小2020/03/09 22:45:47

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.

Simple, semantic.

2020/03/09 22:45:47

[[/ h到@ E.Sundin,以在评论中链接此内容 ]

最佳答案(匿名函数或绑定)将起作用,但它并不是最有效的方法,因为它会为该map()函数生成的每个实例创建事件处理程序的副本

This is an explanation of the optimal way to do it from the 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.

卡卡西Near2020/03/09 22:45:47

这里有不错的答案,我同意@Austin Greco(第二个选项,具有单独的组件),
我喜欢另一种方式,currying
您可以做的是创建一个接受参数(您的参数)的函数并返回另一个接受另一个参数的函数(在这种情况下为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>

请注意,这种方法不能解决在每个渲染器上创建新实例的问题。
与其他内联处理程序相比,我更喜欢这种方法,因为我认为这种方法更加简洁易读。

编辑:
如下面的注释中所建议,您可以缓存/记住函数的结果。

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" />

西里神无Pro2020/03/09 22:45:47

如今,有了ES6,我觉得我们可以使用更新的答案。

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

基本上,(对于任何不知道的对象)由于onClick期望传递给它的功能而bind起作用,因为它创建了功能的副本。相反,我们可以传递一个箭头函数表达式,该表达式仅调用所需的函数并保留this您永远不需要render在React中绑定该方法,但是如果由于某种原因您迷失this了一种组件方法:

constructor(props) {
  super(props);
  this.myMethod = this.myMethod.bind(this);
}
十三前端Harry2020/03/09 22:45:47

简单的方法

使用箭头功能:

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

这将创建一个新的函数,handleSort以正确的参数进行调用

更好的方法

将其提取到子组件中。 在render调用中使用箭头函数的问题是,每次都会创建一个新函数,最终导致不必要的重新渲染。

如果创建子组件,则可以传递处理程序并将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>
);