我想读取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事件传递值?


当前回答

如果您正在使用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>
     );
   }
 }

其他回答

这里有很好的答案,我同意@Austin Greco(第二个选项,有单独的组件)还有一种我喜欢的方式,咖喱。您可以做的是创建一个接受一个参数(您的参数)的函数,并返回另一个接受另一个参数的函数(在本例中是单击事件)。那你就可以随心所欲了。

示例5:

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”];类应用程序扩展React.Component{状态={值A:“”,valueB:“一些初始值”,值C:“”,值D:“废话”};handleChange=param=>e=>{const nextValue=e.target.value;this.setState({[“value”+param]:nextValue});};render(){返回(<div>{someArr.map(obj=>{返回(<div><标签>{`输入${obj}`}</label><输入type=“文本”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>

请注意,这种方法不能解决每次渲染时创建新实例的问题。与其他内联处理程序相比,我更喜欢这种方法,因为在我看来,这种方法更简洁、可读。

编辑:如下面的注释所示,您可以缓存/记忆函数的结果。

这是一个简单的实现:

让备忘录={};const someArr=[“A”,“B”,“C”,“D”];类应用程序扩展React.Component{状态={值A:“”,valueB:“一些初始值”,值C:“”,值D:“废话”};handleChange=param=>{常量处理程序=e=>{const nextValue=e.target.value;this.setState({[“value”+param]:nextValue});}if(!memo[param]){备忘录[param]=e=>处理程序(e)}返回备忘录[param]};render(){返回(<div>{someArr.map(obj=>{返回(<div key={obj}><标签>{`输入${obj}`}</label><输入type=“文本”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,以便在评论中链接此内容]

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

这是对ESLint插件反应最佳方式的解释:

项目列表渲染中绑定的一个常见用例是在渲染列表时每个列表项的单独回调:

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

});

这将加快渲染速度,因为它避免了创建新的函数(通过绑定调用)。

有很多性能方面的考虑,都是在真空中。这个处理程序的问题是,您需要讨好它们,以便将无法在props中命名的参数合并进来。这意味着组件需要每个可单击元素的处理程序。让我们同意,对于几个按钮来说,这不是问题,对吧?当您处理具有数十列和数千行的表格数据时,就会出现问题。在这里,您会注意到创建这么多处理程序的影响。

事实是,我只需要一个。我将处理程序设置在表级别(或UL或OL…),当单击发生时,我可以使用事件对象中的可用数据来判断单击的单元格:

nativeEvent.target.tagName
nativeEvent.target.parentElement.tagName 
nativeEvent.target.parentElement.rowIndex
nativeEvent.target.cellIndex
nativeEvent.target.textContent

我使用标记名字段检查单击是否发生在有效元素中,例如忽略页脚中的单击。rowIndex和cellIndex提供了所单击单元格的确切位置。Textcontent是单击单元格的文本。

这样,我不需要将单元格的数据传递给处理程序,它可以自助处理。如果我需要更多的数据,不需要显示的数据,我可以使用dataset属性或隐藏元素。通过一些简单的DOM导航,一切都在手边。自从PC更容易陷入困境以来,HTML中就一直使用这种方式。

React Hooks解决方案2022

const arr = [
  { id: 1, txt: 'One' },
  { id: 2, txt: 'Two' },
  { id: 3, txt: 'Three' },
]

const App = () => {
  const handleClick = useCallback(
    (id) => () => {
      console.log("ID: ", id)
    },
    [],
  )

  return (
    <div>
      {arr.map((item) => (
        <button onClick={handleClick(item.id)}>{item.txt}</button>
      ))}
    </div>
  )
}

您可以传递一个函数以使用Callback的返回,然后可以通过传递参数在渲染中正常调用函数!只需确保正确设置useCallback的依赖数组。

React>=16的最佳解决方案

我发现在不使用内联函数的情况下调用onClick、onChange等中具有多个参数的函数的最干净的方法是使用React 16和更高版本中提供的自定义数据属性。

const App = () => {
  const onClick = (e) => {
    const value1 = e.currentTarget.getAttribute("data-value1")
    const value2 = e.currentTarget.getAttribute("data-value2")
    const value2 = e.currentTarget.getAttribute("data-value2")
    console.log("Values1", value1)
    console.log("Values2", value2)
    console.log("Values3", value3)
  }
  return (
    <button onClick={onClick} data-value1="a" data-value2="b" data-value3="c" />
  )
}

上面的示例是针对功能组件的,但即使在类组件中,实现也非常相似。

这种方法不会产生不必要的重新渲染,因为您没有使用内联函数,并且可以避免使用这种方法绑定的麻烦。

它允许您在函数中传递任意数量的值。

如果要将值作为道具传递给子组件的onClick中使用的子组件,则也可以在那里使用此方法,而无需创建包装函数。

在您希望将对象的id传递给onClick的情况下,也可以使用对象数组,如下所示。

const App = () => {
  const [arrState, setArrState] = useState(arr)

  const deleteContent = (e) => {
    const id = e.currentTarget.getAttribute("data-id")
    const tempArr = [...arrState]
    const filteredArr = tempArr.filter((item) => item.id !== id)
    setArrState(filteredArr)
  }

  return (
    <div>
      {arrState.map((item) => (
        <React.Fragment key={item.id}>
          <p>{item.content}</p>
          <button onClick={deleteContent} data-id={item.id}>
            Delete
          </button>
        </React.Fragment>
      ))}
    </div>
  )
}

使用封口,可获得干净的解决方案:

<th on单击={this.handleSort(column)}>{column}</th>

handleSort函数将返回已设置值列的函数。

handleSort: function(value) { 
    return () => {
        console.log(value);
    }
}

当用户单击th时,将使用正确的值调用匿名函数。

例子:https://stackblitz.com/edit/react-pass-parameters-example