Validating User Input
Add validation to a form component.
Environment
Use the environment you are most comfortable with. I recommend using create-react-app to create a local version of the project so that you can inspect the DOM easily from your browser when debugging. Alternatively, you can work from a blank React template in CodeSandbox. Starter code is provided after the problem specification.
Specification
Write a functional component that imitates a log-in process. The component should be a form consisting of two input fields — for username and password — and a login button beneath them.
When the user selects Submit or hits enter, the form should check if the username and password entered match some user stored in the component’s state. If so, an alert should appear including the user’s username (as shown below), and the component should reset to its starting state.
If the username and password entered do not match an existing count, then (so long as each field is more than six characters long) create a new account, store it for future log-ins, and display an alert to notify the user. Just as the form does on successful login, it should clear the input fields following the alert.
If the username and/or password entered is less than six characters, do not create a new account, and display an alert explaining the issue. Do not clear the input fields so that the user may append to what they have already entered:
Finally, the user should not be allowed to input more than 20 characters in either field. If the user attempts to add a 21st character to their input, do not reflect their change, and display the error in an alert.
Starter Code
Here is some code to get you started:
import React, { useState } from "react";
function App() {
return (
<div
style={{
display: "flex",
justifyContent: "center",
paddingTop: 20,
}}
>
<ValidatedForm />
</div>
);
}
const ValidatedForm = () => {
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const [accounts, setAccounts] = useState([
{ username: "JohnDoe1", password: "1234567" },
]);
const onSubmit = (e) => {
// YOUR CODE HERE
};
return (
<form
style={{
display: "flex",
flexDirection: "column",
border: "solid",
padding: 10,
}}
onSubmit={onSubmit}
>
<h3>Login</h3>
<input
value={username}
type="text"
onChange={/* MORE OF YOUR CODE HERE */ () => {}}
style={{ marginBottom: 5 }}
/>
<input
value={password}
type="text"
onChange={/* MORE OF YOUR CODE HERE */ () => {}}
style={{ marginBottom: 10 }}
/>
<button style={{ alignSelf: "center" }} onClick={onSubmit}>
Submit
</button>
</form>
);
};
export default App;
The array in the component’s state that stores existing user objects is prepopulated with one user.
Solution
import React, { useState } from "react";
function App() {
return (
<div
style={{
display: "flex",
justifyContent: "center",
paddingTop: 20,
}}
>
<ValidatedForm />
</div>
);
}
const ValidatedForm = () => {
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const [accounts, setAccounts] = useState([
{ username: "JohnDoe1", password: "1234567" },
]);
const userExists = (user, pass) => {
for (const account of accounts) {
if (account.username == user && account.password == pass) {
return true;
}
}
return false;
};
const onSubmit = (e) => {
e.preventDefault(); // prevents page refresh
if (userExists(username, password)) {
alert("Logged in successfully! Hi, " + username + ".");
} else if (username.length > 6 && password.length > 6) {
setAccounts([...accounts, { username, password }]);
alert("Logged in successfully! Welcome, " + username + ".");
} else {
alert("Username and password must be more than 6 characters.");
return;
}
setUsername("");
setPassword("");
};
return (
<form
style={{
display: "flex",
flexDirection: "column",
border: "solid",
padding: 10,
}}
onSubmit={onSubmit}
>
<h3>Login</h3>
<input
value={username}
type="text"
onChange={(e) =>
e.target.value.length < 20
? setUsername(e.target.value)
: alert("Username cannot exceed 20 characters.")
}
style={{ marginBottom: 5 }}
/>
<input
value={password}
type="text"
onChange={(e) =>
e.target.value.length < 20
? setPassword(e.target.value)
: alert("Password cannot exceed 20 characters.")
}
style={{ marginBottom: 10 }}
/>
<button style={{ alignSelf: "center" }} onClick={onSubmit}>
Submit
</button>
</form>
);
};
export default App;
First, to tackle the validation that needs to occur while the user completes the form — namely, the input fields cannot hold more than 20 characters — I use a ternary operator in the onChange
callback of each input element; the input element only updates its own value (held in state) if the new input is less than 20 characters long. The remaining parts of the solution to this challenge are handled in the onSubmit
callback (and the userExists
helper function called by onSubmit
). We stop the default page refresh and walk through a couple of conditional statements to determine the behavior of the form based on the username and password entered.