React Handling Form Submission
Intro
We will continue to work with this simple text input that we are turning into a search bar.
class SearchBar extends React.Component {
// here we decide what to do with those changes
state = { term: "" };
render() {
return (
<div className="ui segment">
<form className="ui form">
<div className="field">
<label>Image Search: </label>
<input
type="text"
value={this.state.term}
onChange={(e) => this.setState({ term: e.target.value })}
/>
</div>
</form>
</div>
);
}
}
We have already turned this into a controlled element where the value of the input is now decided by the state of the component, which is updated every time the value of the input is changed.
Default Form Submission Behavior
Currently when the user presses enter on the form the page will reload and behind the scenes, the html form is attempting to send a POST request to the server backend. We don’t have a backend to handle this post request. What we want to do is hijack this default behavior and do something else.
Prevent Default Behaviour
To prevent the default form submission behavior we create a new event handler that intercepts the form submission and that event handler uses the .preventDefault()
method.
class SearchBar extends React.Component {
// here we decide what to do with those changes
state = { term: "" };
onFormSubmit(event) {
event.preventDefault();
}
render() {
return (
<div className="ui segment">
<form onSubmit={this.onFormSubmit} className="ui form">
<div className="field">
<label>Image Search: </label>
<input
type="text"
value={this.state.term}
onChange={(e) => this.setState({ term: e.target.value })}
/>
</div>
</form>
</div>
);
}
}
At this point we have not specified what we want to do on submission, we have just intercepted and prevent the default behavior (submitting a post request and reloading the page).
The Most Common Error In React: this is undefined
At this point you would think that we could add the following to the onFormSubmit
method
onFormSubmit(event) {
event.preventDefault();
console.log(this.state.term);
}
But if you tried to submit the form now you would get the following error.
We have an issue where this
is undefined, because components do not auto-bind methods to themselves. This can be very confusing, there are some good posts about this.
Or for a more in depth look at the this keyword in general I have a good post here:
Ncoughlin: This Keyword and Object Oriented Programming
In short, we can covert this to an arrow function, because one of the features of arrow functions is that they automatically bind this
.
onFormSubmit = (event) => {
event.preventDefault();
console.log(this.state.term);
}
And now we successfully get the feedback in the console when we submit the input.
Communicating Child to Parent
So far we have worked with props to send information from parent elements to child elements. However now we have the problem of needing to send information from our child element (the search bar component) to it’s parent element (the App component). To do that we will be invoking callbacks.
Invoking Callback
The short explanation is that we define a function in the parent component that describes what we want to do with the input. Then we pass that function into the child component with a prop. So in effect the function is living in the parent app for organizational purposes, but it is being executed inside of the child component. Here is the parent component App
class App extends React.Component {
onSearchSubmit(input) {
console.log(input);
}
render() {
return (
<div className="ui container" style={{ marginTop: "10px" }}>
<SearchBar onSubmit={this.onSearchSubmit} />
</div>
);
}
}
Note that we have converted the component to a class component. Then we have defined the function onSearchSubmit which is where we are describing what we want to do with the search term. Right now we are just logging it in the console.
This function takes one argument, which is going to be the value of the field when it is submitted.
onSearchSubmit(input) {
console.log(input);
}
Then down in the SearchBar
component JSX we are creating a prop called onSubmit and passing in our new function.
<SearchBar onSubmit={this.onSearchSubmit} />
Note that inside of the child component we were required to us the name onSubmit or onChange because those were hardcoded methods on html elements. Here we can use any term we want because it is simply a prop on a component. We are still going to use the term onSubmit because it is a good descriptor of when this prop will be invoked.
Then if we go back to our child component, the search bar we can see the following.
class SearchBar extends React.Component {
state = { term: "" };
onFormSubmit = (event) => {
event.preventDefault();
this.props.onSubmit(this.state.term);
}
render() {
return (
<div className="ui segment">
<form onSubmit={this.onFormSubmit} className="ui form">
<div className="field">
<label>Image Search: </label>
<input
type="text"
value={this.state.term}
onChange={(e) => this.setState({ term: e.target.value })}
/>
</div>
</form>
</div>
);
}
}
We have added to our onFormSubmit
function
this.props.onSubmit(this.state.term);
which is referencing the function we wrote in the parent App component and passed in with a prop, and then submitting as it’s argument the contents of the form, which are tracked with state.term.
And when does this prop function actually get called?
<form onSubmit={this.onFormSubmit} className="ui form">
onSubmit
So have we really passed the value to the parent element? I would say no. We have written the functionality in the parent element, and then passed the functionality down to the child, where the argument that the function requires are being stored.
But the effect is basically the same, and we will see this pattern frequently.
The net effect is that the onSearchSubmit
function from the parent App component is running when the form is submitted. And because the function is being referenced in the App component, if you check the console, the JS file that is referenced next to the console log is in fact the App.js file. The prop is not copying the function down, it is referencing back up to itself.
Comments
Recent Work
Basalt
basalt.softwareFree desktop AI Chat client, designed for developers and businesses. Unlocks advanced model settings only available in the API. Includes quality of life features like custom syntax highlighting.
BidBear
bidbear.ioBidbear is a report automation tool. It downloads Amazon Seller and Advertising reports, daily, to a private database. It then merges and formats the data into beautiful, on demand, exportable performance reports.