1
\$\begingroup\$

I created an example of a simple form for multiple inputs (name and phone number) in React. If the user enters invalid data in input field, error text is displayed near the same field. I learned a lot of different examples of the form validation using React and I don't understand where is the better place for validation checking in form.

import React from 'react'
import { render } from 'react-dom'
const ErrorOutput = props => {
 let name = props.name
 let inputValue = props.case
 if (name === 'firstName') {
 if (!inputValue.match(/^[a-zA-Z]+$/) && inputValue.length > 0) {
 return <span>Letters only</span>
 }
 return <span></span>
 }
 if (name === 'telNo') {
 if(!inputValue.match(/^[0-9]+$/) && inputValue.length > 0) {
 return <span>Numbers only</span>
 }
 return <span></span>
 }
}
class App extends React.Component {
 constructor(props){
 super(props)
 this.state = {
 firstName: '',
 telNo: ''
 }
 }
 handleValidation(e) { 
 this.setState({
 [e.target.name]: e.target.value 
 }) 
 }
 render() {
 return (
 <form>
 <label>
 First name:
 </label>
 <input
 type='text'
 name ='firstName'
 value = {this.state.firstName}
 onChange = {this.handleValidation.bind(this)}
 />
 <ErrorOutput case={this.state.firstName} name={'firstName'} />
 <label>
 Phone number:
 </label>
 <input
 type='tel'
 name ='telNo'
 value = {this.state.telNo}
 onChange = {this.handleValidation.bind(this)}
 />
 <ErrorOutput case={this.state.telNo} name={'telNo'} />
 </form>
 )
 }
}
render(
 <App />,
 document.getElementById('root')
)
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked May 23, 2018 at 13:15
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

A pattern I use for this is individual validators:

function validateName(value) {
 if (value.length > 0) {
 if (!inputValue.match(/^[a-zA-Z]+$/)) {
 return 'Letters only'
 }
 }
 return ''
}

Obviously this can be heavy for simple forms, but it's a very reusable pattern, and it keeps your components lighter:

handleValidation(e) {
 const name = e.target.name
 const value = e.target.value 
 this.setState({ [name]: value }, () => {
 if (name === 'firstName') {
 this.setState({ errors[name]: validateName(value) })
 }
 }) 
}

This allows you to do:

{this.state.errors['firstName'] && <div className="form-error">{this.state.errors['firstName']}</div>}

One benefit I find to this pattern is that it scales well - as your forms grow, you'll refactor to have your inputs as their own components and managing their own state, and this pattern will scale better and better as you refactor, as opposed to doing all the checking within a single function.

answered Nov 30, 2018 at 15:07
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.