The React documentation explains how to handle HTML forms and events. Let’s have a look.
Imagine you have an HTML form with an <input>
field: the browser will open a new page when the user submits the form.
In React, we often don’t want that because we handle our state as part of the main component and we mutate it with setState()
. This is a “controlled component”.
Here’s an example:
App.js
...
class App extends Component {
state = {
// some state
route: "signin"
};
...
onRouteChange = (route) => {
this.setState(() => ({ route: route }));
}
...
render() {
return (
...
<Signin onRouteChange={this.onRouteChange} />
...
}
}
The App
component passes its method onRouteChange
as a prop to the SignIn
component.
Signin.js
const Signin = ({ onRouteChange }) => {
return (
...
<article>
<main>
<form className>
<div className>
<input
type="submit"
value="Sign in"
onClick={() => onRouteChange("home")}
/>
</div>
</main>
</article>
...
);
};
When the user clicks on the input
field, it fires off the event handler onClick
- a Synthetic Event. But with the default behavior, the form tries to connect with a method, i.e. a POST method to send the data to the backend server.
We now have an error: “Form submission canceled because the form is not connected.”
You can prevent this HTML behavior with preventDefault()
and the docs even have an example.
from the official documentation:
function ActionLink() {
function handleClick(e) {
e.preventDefault();
console.log("The link was clicked.");
}
return (
<a href="#" onClick={handleClick}>
Click me
</a>
);
}
But it doesn’t work out of the box when you pass the function (which is an object method of the class App
as a React component) as prop to another component (the Signin
component).
In your App
component, add event
as an additional parameter to the method and add preventDefault()
in the function body:
App.js
...
onRouteChange = (event, route) => {
event.preventDefault();
this.setState(() => ({ route: route }));
}
...
Now use the magic of closures and higher order functions and change your Signin onClick
handler:
Signin.js
const Signin = ({ onRouteChange }) => {
return (
...
<article>
<main>
<form className>
<div className>
<input
type="submit"
value="Sign in"
onClick={(event) => onRouteChange(event, "home")}
/>
</div>
</main>
</article>
...
);
};
The callback function for onClick
now takes the additional parameter event
and returns the onRouteChange
function. This function takes the event
and the route
“home”. When the callback function executes, onRouteChange
will run event.preventDefault()
.
Some things are complicated in Javascript land.