【问题标题】:How to pass in a second argument on ReactJS onSubmit function call如何在 ReactJS onSubmit 函数调用中传递第二个参数
【发布时间】:2016-07-28 23:22:22
【问题描述】:

这里是代码

import React from "react";

var newForm = React.createClass({
    handleSubmit: function (e, text) {
        e.preventDefault();
        console.log(text);
    },
    render: function () {
        return (
            <form onSubmit={this.handleSubmit("react!!!")}>
                <input type="text"/>
            </form>
        );
    }
)};

module.exports = newForm;

我想要实现的是,当我提交表单时,我想要字符串“react!!!”在控制台打印出来,防止默认事件同时发生。

显然,将参数传递给“handleSubmit”函数会破坏代码。

是否可以将 onSubmit 事件中的参数传递给附加到该事件的函数?

【问题讨论】:

  • onSubmit={event =&gt; this.handleSubmit(event, "react!!!")}
  • 没有任何情况,你的render 方法应该知道handleSubmit 不知道的东西——要么是道具,要么是状态,要么是其他任何地方的常量定义。如果没有,你有一些代码味道......

标签: javascript reactjs


【解决方案1】:

你可以对函数进行柯里化

handleSubmit: text => event => {
  event.preventDefault()
  console.log(text)
}

<form onSubmit={this.handleSubmit('react!!!')}>
  ...

等效的 ES5 代码

handleSubmit: function(text) {
  return function(event) {
    event.preventDefault()
    console.log(text)
  }.bind(this)
}

您的代码很奇怪,因为您混合了 ES6 和 ES5 样式。如果您使用的是 ES6 导入,则不妨在其余代码中使用 ES6

import {Component} from 'react'

class NewForm extends Component {
  handleSubmit (text) {
    return event => {
      event.preventDefault()
      console.log(text)
    }
  }
  render() {
    return (
      <form onSubmit={this.handleSubmit('react!!!')}>
        <input type="text">
      </form>
    }
  }
}

export default NewForm

或者更好,因为你的组件不使用任何状态,你可以使用Stateless Functional Component

import {Component} from 'react'

const handleSubmit = text=> event=> {
  event.preventDefault()
  console.log(text)
}

const NewForm = props=> (
  <form onSubmit={handleSubmit('react!!!')}>
    <input type="text">
  </form>
)

export default NewForm

【讨论】:

  • 这很聪明,但遇到了我在回答中概述的相同问题,即您在每次渲染时都创建了一个新函数,这对于垃圾收集抖动来说并不理想。
  • 约翰,如果我错了,请纠正我,但除非元素的某些部分发生变化,否则不会重新渲染元素。无论哪种方式,这都是过早的优化。除非这种形式处于高容量循环的中间,否则不会产生影响。
  • 嗯,任何时候元素或它们的任何父元素被重新渲染时都会重新渲染,这是由于状态或道具发生变化而发生的。重新渲染可能会经常发生,尤其是在表单中由于键盘事件(取决于事物的结构)。当然,onSubmit 是一个可能不经常调用的事件,但事件处理程序是一些东西它们经常使用,我认为值得知道将任何类型的匿名函数放在渲染方法中是低效的。
  • eslint 现在也警告这种模式;避免在渲染中创建新函数是一种很好的做法。
  • 公平地说,在这种情况下,使用箭头函数可能没问题;但是,如果您知道这是解决此问题的主要方法,然后将其应用于另一种情况(例如,在您可以过滤数百个单元格的表格中),突然之间,效率低下会加起来。与开发一样,这是一个权衡问题。我只是想强调解决这个特定问题的各种方法的优缺点。
【解决方案2】:

是的,但你不应该这样做。您当前所做的是说“将 onSubmit 处理程序设置为调用 this.handleSubmit('react!!!') 的结果”。相反,可行的是去:

<form onSubmit={e => this.handleSubmit(e, "react!!!")}>

这当然只是简单的说法:

<form onSubmit={function(e) { this.handleSubmit(e, "react!!!"); }}>

然而,虽然这会起作用,但它所做的是在每次调用 render 时定义一个新的匿名函数。 Render 可以经常被调用,所以这最终会导致一堆新函数一直被创建,这可能会导致性能问题,因为它们需要被垃圾收集和清理。

更好的是拥有一个能够自行查找所需数据的功能。我有两种不同的方法来解决这个问题:

  • 要么把相关数据存储在props中,这样就可以从this.props拉出来了
  • 或者,将相关数据存储在 DOM 中(使用 HTML 5 data attributes),然后使用 javascript 将它们拉出。由于您在被调用的事件处理程序中获得了事件目标,因此您可以使用它来提取您存储的任何数据属性。例如,您可以像这样声明您的表单:

    &lt;form data-somefield={something.interesting} onSubmit={this.handleSubmit}&gt;

您可以通过以下方式在 handleSubmit 中访问:

handleSubmit: function(e) {
    console.log(e.target.dataset.somefield);
}

需要注意的是 a) 像这样在 DOM 中存储数据感觉不是很符合 React 的习惯,并且 b) 如果你将它用于带有嵌套元素的 onClick 事件,你可能会发现你必须爬上 DOM层次结构以查找数据的存储位置。例如,如果您有一个具有数据属性和 onClick 的 div,但它包含一个跨度和一个图像,那么当您单击图像时,onClick 处理程序可能会将其视为目标元素,这意味着您必须上到父级查找具有您要查找的数据属性的 div。

因此,最好只在组件的 props 中包含您想要的数据,然后在事件处理程序中将其拉出。

【讨论】:

  • 我认为这个答案后面的建议太过分了,无法避免使用简单的功能;任何好的 javascript 程序的基本构建块。请记住使用您的分析器,并且仅在性能被证明存在问题时才进行非惯用更改。
  • 我同意第二个建议是不太理想的解决方案,原因我已经解释过了。我记得有一个 &lt;ul&gt; 标签和一堆 &lt;li&gt;'s 我想有一个 onClick 事件,它也将传递他们的 ID 以采取行动。它最终对我概述的警告感到痛苦,所以将来我可能会创建一个新组件,以便我可以通过道具传递我需要的相关信息。
  • 那完全不同。在这种情况下,您应该在&lt;ul&gt; 上有一个onClick 处理程序,然后使用event.srcElement 引用单击的&lt;li&gt;
  • 最终我让它工作得很好,与简单地创建一个新组件以将 ID 作为道具传递相比,这比它的价值要麻烦得多。它确实没有完全不同,因为我们仍在讨论能够将附加信息与事件一起传递给它的事件处理程序。
  • 好吧,您可能已经完成了比您必须做的更多的工作。我猜是苹果和橙子。我给你做了一个小提琴来证明我在说什么。即使有很多孩子对一个事件采取行动,他们也不需要独立的听众。这是一个 jsfiddle 来演示:jsfiddle: z0ue9ss3
猜你喜欢
  • 2021-09-05
  • 1970-01-01
  • 2011-03-08
  • 1970-01-01
  • 1970-01-01
  • 2019-07-05
  • 1970-01-01
  • 1970-01-01
  • 2018-11-07
相关资源
最近更新 更多