Frontend Serverless with React and GraphQL
Start at the beginning and work your way through this project. The code for each step as well as the finished project can be found in the Github repository.
29. Add a Form Input
Objective: Create a GenerateInput component that will allow for users to enter text that is saved into the form.
In the previous step we created the form that will contain all of the fields for creating a recipe. In this step we will create a <GenerateInput>
component which can be used for allowing users to enter text inputs.
components/GenerateFields.tsx
import { Row, Col, Form, Input } from 'antd';type InputType = {name: string;value: string;handleInputChange?: (event: any) => void;};export const GenerateInput = ({name,value,handleInputChange,}: InputType) => (<Row><Col span={12} offset={6}><Form.Item label={`${name}`}><Inputplaceholder={`${name}`}name={`${name}`}value={value}onChange={handleInputChange}/></Form.Item></Col></Row>);
The <Input>
works as a controlled component because it receives its value from the value
parameter and after a change has been made, we call an onChange
handler which will take the updated contents of the input field and assigns it to a state that we are storing in the submitForm
hook. We also need to add the handleInputChange
function to the submitForm
hook. This function will clone the current state of the form and update the field that changed with the new contents of the field. We ensure that the keys of the submitForm
state object matches the name
in the <Input>
component so that we can easily know where to update the field when using the _.set()
function call in the handleInputChange
function.
utils/submitForm.ts
import { useState } from 'react';import * as _ from 'lodash';export const submitForm = (initialValues, callback) => {const [inputs, setInputs] = useState(initialValues);const handleInputChange = (event) => {event.persist();setInputs((inputs) => {const newInputs = _.cloneDeep(inputs);_.set(newInputs, event.target.name, event.target.value);return newInputs;});};const handleSubmit = () => {callback();setInputs(() => ({ ...initialValues }));};return {inputs,handleSubmit,handleInputChange,};};
After creating the new <GenerateInput>
component and updating the submitForm
hook to handle form changes, we can actually use the <GenerateInput>
in our form to manage the title
parameter. We will show in the next step that adding additional parameters in recipe is as simple as calling the <GenerateInput>
for each text input field.
components/CreateRecipe.tsx
import { Row, Col, Form, Button } from 'antd';import { submitForm } from '../utils/submitForm';import { GenerateInput } from './GenerateFields';export const CreateRecipe = () => {const initiateCreateRecipe = () => {console.log('submitted form');};const { inputs, handleInputChange, handleSubmit } = submitForm({title: '',description: '',},initiateCreateRecipe,);return (<Form onFinish={handleSubmit}><GenerateInputname="title"value={inputs.title}handleInputChange={handleInputChange}/><GenerateInputname="description"value={inputs.description}handleInputChange={handleInputChange}/><Row><Col span={16} /><Col span={4}><Form.Item label="Create Recipe"><Button type="primary" htmlType="submit">Create Recipe</Button></Form.Item></Col></Row></Form>);};