Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass in a second argument on ReactJS onSubmit function call

Here are the codes

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;

What I want to achieve with this is that when I submit the form, I want the string "react!!!" to be printed out in the console and prevent the default event from taking place at the same time.

Obviously, passing in the argument to "handleSubmit" function breaks the code.

Is there anyway to pass in an argument from onSubmit event to the functions attached to this event?

like image 620
oosniss Avatar asked Jul 28 '16 23:07

oosniss


People also ask

How do you pass an argument to a function in react?

To pass an event and parameter onClick in React: Pass an inline function to the onClick prop of the element. The function should take the event object and call handleClick . Pass the event and parameter to handleClick .

How do you pass a function from one component to another in react?

For passing the data from the child component to the parent component, we have to create a callback function in the parent component and then pass the callback function to the child component as a prop. This callback function will retrieve the data from the child component.

How do you call a function on onSubmit?

You can put your form validation against this event type. The following example shows how to use onsubmit. Here, we are calling a validate() function before submitting a form data to the webserver. If validate() function returns true, the form will be submitted, otherwise it will not submit the data.


2 Answers

Yes, but you shouldn't do it. What you are currently doing is saying 'set the onSubmit handler to being the result of calling this.handleSubmit('react!!!')'. What would work instead is to go:

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

which is of course just the short form of saying:

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

However, although this will work, what this is doing is defining a new anonymous function every time render is called. Render can be called often, so this will end up with a bunch of new functions being created all the time, which can cause perf issues as they need to be garbage collected and cleaned up.

What is better is to have a function which is capable of finding the data you need on its own. There are 2 different ways which I use to address this:

  • Either store the relevant data in props, so that it can be pulled out from this.props
  • Or, store the relevant data in the DOM (using HTML 5 data attributes), and then pull them out using javascript. Since you are given the event target in the event handler that is called, you can use it to pull out any data attributes you have stored. For example you might declare your form like this:

    <form data-somefield={something.interesting} onSubmit={this.handleSubmit}>

which you could access in handleSubmit by going:

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

The caveat there being that a) storing data in the DOM like this doesn't feel very idiomatic React, and b) if you use this for onClick events with nested elements, you might find that you have to climb up the DOM hierarchy to find where your data is stored. As an example if you have a div with a data attribute and an onClick but it contains a span and an image, when you click the image it's possible that is what the onClick handler will see as it's target element, meaning you'd have to go up to the parent to find the div with the data attribute you're looking for.

So it's probably best to just include the data you want in your component's props and pull it out from there in your event handler.

like image 199
John Avatar answered Oct 25 '22 13:10

John


You can curry the function

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

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

Equivalent ES5 code

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

Your code is weird though because you're mixing ES6 and ES5 styles. If you're using ES6 imports, you might as well use ES6 in the rest of your code

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

Or better, since your Component doesn't use any state, you can use a 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
like image 45
Mulan Avatar answered Oct 25 '22 13:10

Mulan