Lifting State Up with React and Submitting a Form

Use Case: Maintain your application's state in a parent component so that you can separate your views.

Below is a code example of how I manage state on page's where I have both a contact form and a confirmation message. The main page module maintains the state, the child form component receives and updates the state, and the child confirmation message component receives the first name state property via a prop on the submission of the form.

The page maintaining the state

The form's page module holds and maintains the state and passes its own handleChange and handleSubmit functions to the child form component:

JavaScript

import ConfirmationMessage from '../components/ConfirmationMessage'
import ContactForm from '../components/ContactForm'

class Page extends React.PureComponent {

	constructor(props) {
		super(props)
		this.state = {
			submitted: false, first: '', last: '', email: '', phone: '', message: '', ip: '', url: ''
		}
	this.handleChange = this.handleChange.bind(this)
	this.handleSubmit = this.handleSubmit.bind(this)
}

	handleChange = (e) => {
		const target = e.target
		const value = target.type === 'checkbox' ? target.checked : target.value
		const name = target.name
		if (name !== 'ip') {
			this.setState({
				[name]: value
			})
		}
	}

	handleSubmit = (e) => {
		// POST request to API
		this.setState({submitted: true})
		e.preventDefault()
	}

	render() {
		const values = {
			first: this.state.first,
			last: this.state.last,
			email: this.state.email
		}

		if (this.state.submitted) {
			return <ConfirmationMessage first={this.state.first} />
		}
		return <ContactForm onInputChange={this.handleChange} onFormSubmit={this.handleSubmit} {...values}/>
	}
}

The form

The form itself both receives and updates the state of the page module by leveraging the function handleChange passed to it via the props.

JavaScript

class Form extends React.PureComponent {

	constructor(props) {
		super(props)
		this.handleChange = this.handleChange.bind(this)
		this.handleSubmit = this.handleSubmit.bind(this)
	}

	handleChange(e) {
		this.props.onInputChange(e)
	}

	handleSubmit(e) {
		this.props.onFormSubmit(e)
		e.preventDefault()
	}

	render() {
		return (
			<form onSubmit={this.handleSubmit}>
				<div className='form-section'>
					<label>Name</label>
						<input type='text' name='first' placeholder='First' required value={this.props.first} onChange={this.handleChange} />
						<input type='text' name='last' placeholder='Last' required value={this.props.last} onChange={this.handleChange} />
				</div>
				<label> Email
					<input type='email' name='email' required value={this.props.email} onChange={this.handleChange} />
				</label>
				<input type='submit' value='Submit' />
			</form>
		)
	}
}

export default Form

The confirmation message

The confirmation message component receives the first name submitted by the form as a prop.

JavaScript

export default (props) => (
	<p className='form-confirmation'>Thanks for your message, {props.first}. We'll get back to you shortly.</p>
)

Tweet me @tylerewillis

Or send an email:

And support me on Patreon