Как создавать простые формы JSX с помощью перехватчика useState

Введение

Формы — важнейшие компоненты Интернета, независимо от того, созданы ли они с помощью HTML или с помощью таких фреймворков, как React. Формы позволяют пользователям отправлять данные, выполнять основные задачи в Интернете, такие как публикация твита, отправка сообщения или покупки в Интернете, а также извлекать данные. Формы — это основа Интернета, и без них создание сетей было бы невозможно.

Создание эффективных форм является необходимостью для разработчиков, поскольку позволяет им собирать данные от пользователей эффективным и простым для понимания способом. Когда формы хорошо спроектированы, они могут помочь разработчикам избежать ошибок и обеспечить сбор необходимых им данных. Кроме того, эффективные формы могут помочь улучшить взаимодействие с пользователем, упрощая предоставление пользователям необходимой информации.

В отличие от форм HTML, React позволяет динамическую обработку данных формы. При работе с формами в HTML или стандартном Javascript важно помнить, что входные данные можно обрабатывать только после отправки формы. Это означает, что любые изменения, внесенные пользователем, не будут отслеживаться до самого конца процесса. Однако в React у нас есть возможность создавать состояния, которые могут отслеживать каждое изменение, внесенное во время взаимодействия пользователя с формой. Это мощный инструмент, который может значительно улучшить пользовательский опыт и сделать процесс намного более эффективным. Обработка информации начинается, как только пользователь начинает взаимодействовать с формой. Это означает, что после отправки формы мы отправляем данные и передаем состояние, которое отслеживали все это время.

React предлагает два способа обработки данных в формах: первый способ — через неконтролируемые компоненты, которые позволяют DOM обрабатывать элементы формы и данные. Второй способ — через контролируемые компоненты, где данные полностью обрабатываются React посредством перехватчиков.

Предварительные условия

  • Знание HTML, особенно HTML-форм и элементов форм, а также CSS.
  • Знание Javascript
  • Знание ДОМ.
  • Базовые знания React и хука useState.
  • Текстовый редактор для написания кода

Создание форм с помощью неконтролируемых компонентов

В неконтролируемых компонентах состоянием элементов формы управляет не React, а DOM. Когда пользователи вводят текст в поля формы в неконтролируемых компонентах, браузер контролирует состояние этих элементов и обновляет DOM для этого элемента.

Здесь для элементов формы не установлено свойство значения, вместо этого мы используем обработчик событий onChange для получения вводимых пользователем данных. Продолжая этот урок, мы:

  • Создание базовых форм
  • Управляйте состоянием ввода с помощью хука useState

Создание простых форм

Сначала создайте файл Form.js и импортируйте react и useState.

import React, { useState } from "react"

Затем экспортируйте функцию Form по умолчанию, вернув в нее элемент form.

export default function Form () {
    return (
        <form>

        </form>
    )
}

Затем создайте элемент input внутри формы с типом и заполнителем First name и событием onChange, передав функцию handleChange. Как показано ниже

import React, { useState } from "react"

export default function Form () {
    return (
        <form>
            <input type="text" placeholder="First Name" onChange={handleChange} />
        </form>
    )
}

Итак, давайте обработаем изменения во входных данных First name с помощью хука useState. Давайте просто создадим функцию handleChange и console.log для проверки изменений во входных данных.

Функция handleChange должна быть вложена внутри компонента формы, как показано ниже.

import React, { useState } from "react"

export default function Form () {

    function handleChange() {
        console.log("Changed!")
    }

    return (
        <form>
            <input type="text" placeholder="First Name" onChange={handleChange} />
        </form>
    )
}

Итак, мы можем проверить и увидеть это, введя в поле ввода «Изменено!». выводится на консоль

Далее мы используем let для объявления переменной firstName и console.log firstName для просмотра изменений во вводе пользователя по мере его ввода.

import React, { useState } from "react"

export default function Form () {

    let firstName

    console.log(firstName)


    function handleChange() {
        console.log("Changed!")
    }

    return (
        <form>
            <input type="text" placeholder="First Name" onChange={handleChange} />
        </form>
    )
}

В нашей функции-обработчике onClick мы передаем event в нашу функцию, затем убираем там console.log, заменяя его кодом

function handleChange(event) {
        firstName = event.target.value
    }

Код будет выглядеть следующим образом

import React, { useState } from "react"

export default function Form () {

    let firstName

    console.log(firstName)


    function handleChange(event) {
        firstName = event.target.value
    }

    return (
        <form>
            <input type="text" placeholder="First Name" onChange={handleChange} />
        </form>
    )
}

Давайте запустим файл и посмотрим вывод в консоли.

Мы видим, что, несмотря на многократный набор текста, в нашей консоли ничего не происходит, поскольку React не может обнаружить изменения в firstName, поэтому мы используем хук useState, чтобы объявить нашу переменную и установить состояние, позволяющее вносить изменения в firstName.

Сначала мы объявляем массив firstName и setFirstName, равный useState, который устанавливается в пустую строку.

    const [firstName, setFirstName] = useState("")

Затем мы передаем объект события из обработчика событий onClick в нашу функцию handleClick, а затем заменяем console.log, чтобы обновлять состояние firstName при каждом нажатии клавиши.

function handleChange(event) {
        setFirstName(event.target.value)
    }

Затем добавьте console.log в тело функции формы, чтобы видеть изменения в вводе пользователя по мере его ввода.

import React, { useState } from "react"

export default function Form () {

    const [firstName, setFirstName] = useState("")

    console.log(firstName)


    function handleChange(event) {
        setFirstName(event.target.value)
    }

    return (
        <form>
            <input type="text" placeholder="First Name" onChange={handleChange} />
        </form>
    )
}

Мы видим, что, в отличие от предыдущей попытки, React способен обнаруживать изменения во входных данных и соответствующим образом обновлять firstName.

Добавление еще одного поля ввода в форму

Мы можем добавить еще одно поле ввода в форму двумя способами, и в этом разделе мы рассмотрим оба способа.

А. Дублирование нашего прежнего кода путем добавления еще одного хука

Дублируя наш прежний код и аккуратно его отредактировав, мы можем добавить еще одно поле input, а также отслеживать и обновлять его состояние в React, как мы это делали раньше.

Мы создаем переменную состояния surName с помощью хука useState.

const [surName, setSurName] = useState("")

Следующим шагом будет создание функции handleSurName, используя функцию handleChange в качестве модели.

import React, { useState } from "react"

export default function Form () {

    const [firstName, setFirstName] = useState("")
    const [surName, setSurName] = useState("")


    function handleChange(event) {
        setFirstName(event.target.value)
    }

    function handleSurName(event) {
        setSurName(event.target.value)
    }


    return (
        <form>
            <input type="text" placeholder="First Name" onChange={handleChange} />
            <input type="text" placeholder="surName" onchange={handleSurName} />

        </form>
    )
}

Затем console.log firstName и surName, чтобы мы могли увидеть вывод.

Однако если у нас будет больше входных данных, мы будем дублировать больше кода, что приведет к получению кода низкого качества, который может затруднить поддержку. В следующем разделе мы узнаем, как сделать то же самое в более чистом и приемлемом формате.

Б. Объединение состояния в объект

Комбинируя состояния, мы можем создавать и поддерживать одно состояние для управления несколькими входами. Это позволяет нам использовать одно состояние для контроля и управления несколькими входами, флажками и радиоэлементами. Это дает нам больший контроль, упрощает код и повышает его качество, особенно если код будет использоваться другими разработчиками.

Сначала мы дублируем handleSurName и переменную состояния и заменяем заполнитель surName на lastName, так как это легко понять, и передаем ему handleChange.

import React, { useState } from "react"

export default function Form () {

    const [firstName, setFirstName] = useState("")


    function handleChange(event) {
    }


    return (
        <form>
            <input type="text" placeholder="First Name" onChange={handleChange} />
            <input type="text" placeholder="lastName" onchange={handleChange} />

        </form>
    )
}

Чтобы создать единое состояние, которое может использоваться всеми типами ввода, нам нужно создать объект в состоянии. Переменная состояния может принимать несколько типов данных, поэтому мы создаем объект в состоянии. Нам нужно изменить имя переменной с firstName на что-то более общее, например formFields.

import React, { useState } from "react"

export default function Form () {

    const [formFields, setFormFields] = useState({
        firstName: "",
        lastName: ""
    })


    function handleChange(event) {
    }


    return (
        <form>
            <input type="text" placeholder="First Name" onChange={handleChange} />
            <input type="text" placeholder="lastName" onchange={handleChange} />

        </form>
    )
}

К сожалению, мы не можем использовать event.target.value для получения данных из полей формы, поскольку вместо предоставления нам данных в форме объекта наш объект будет стерт, и на выходе будет строка, что бесполезно. Поскольку мы используем одну и ту же функцию handleChange для обоих входов, нам нужен способ определить, какой вход вызвал событие. Для этого мы даем входным данным свойство name, соответствующее имени свойства, которое мы сохраняем.


          <input 
                type="text" 
                placeholder="First Name" 
                onChange={handleChange} 
                name="firstName" 
                />

            <input 
                type="text" 
                placeholder="Last Name" 
                onChange={handleChange} 
                name="lastName" 
                />

Чтобы проверить, работает ли наш код, мы console.log event.target.name проверим, какое поле ввода запускает прослушиватель событий. Давайте проверим наш код

Благодаря этому у нас есть все необходимое для вызова formFields и корректного обновления нашего объекта. Для этого мы вызываем setFormFields, чтобы принять изменения в состоянии и соответственно обновить нашу переменную formFields. Мы вызовем setFormFields в нашей функции onChange, а затем передадим наше предыдущее состояние (мы не делали этого со строками, потому что перезапись нашего файла фактически ничего не меняет), предотвращая полную перезапись нашего предыдущего состояния, передавая обратный вызов функция, которая затем вернет объект. Объект принимает копию предыдущего состояния, затем ему передается конкретное свойство, которое мы хотим изменить в объекте. Это приводит к перезаписанию только значения свойства, которое мы хотим изменить, при сохранении других компонентов объекта.

import React, { useState } from "react"

export default function Form () {

    const [formFields, setFormFields] = useState({
        firstName: "",
        lastName: ""
    })

    function handleChange(event) {
        setFormFields(prevState => {
            return {
                ...prevState,
                [event.target.name]: event.target.value
            }
        })
    }

    return (
        <form>
            <input 
                type="text" 
                placeholder="First Name" 
                onChange={handleChange} 
                name="firstName" 
                />

            <input 
                type="text" 
                placeholder="Last Name" 
                onChange={handleChange} 
                name="lastName" 
                />
        </form>
    )
}

Вычисляемые свойства использовались для преобразования динамической строки event.target.name и использования ее в качестве имени свойства объекта. Console.log formFields чтобы увидеть наше состояние по мере его изменения

Изначально объект пуст, но когда мы начинаем печатать, объект начинает меняться, а наше состояние остается неизменным.

Добавление другого входа

Добавить еще одно поле ввода будет очень просто, поскольку нам просто нужно добавить новое поле к нашему объекту состояния, а не добавлять еще одну функцию обработчика событий и новое состояние.

Давайте продемонстрируем это, добавив поле Имя пользователя в наш объект состояния. Пожалуйста, убедитесь, что имя свойства в объекте состояния совпадает с именем во входном теге.

import React, { useState } from "react"

export default function Form () {

    const [formFields, setFormFields] = useState({
        firstName: "",
        lastName: "",
        userName: ""
    })


    function handleChange(event) {
        setFormFields(prevState => {
            return {
                ...prevState,
                [event.target.name]: event.target.value
            }
        })
    }


    return (
        <form>
            <input 
                type="text" 
                placeholder="First Name" 
                onChange={handleChange} 
                name="firstName" 
                />

            <input 
                type="text" 
                placeholder="Last Name" 
                onChange={handleChange} 
                name="lastName" 
                />

            <input 
                type="text" 
                placeholder="Username" 
                onChange={handleChange} 
                   name="userName" 
                  />

        </form>
    )
}

Давайте добавим favColour к объекту состояния.

const [formFields, setFormFields] = useState({
        firstName: "",
        lastName: "",
        userName: "",
        description: "",
        isTrue: true,
        tiers: "",
        favColour: ""
    })

Затем мы добавляем name, value и обработчик событий onChange к элементу select.

<select id="favColour" name="favColour" value={formFields.favColour} onChange={handleChange} >

С этими строками кода раскрывающийся список работает так, как ожидалось.

Однако начальное значение элемента select представляет собой пустую строку, но параметр, представляющий пустую строку, отсутствует. Мы можем решить эту проблему, создав элемент option с пустым строковым значением.

<option value="">-- Choose --</option>

И это полный код

import React, { useState } from "react"

export default function Form () {

    const [formFields, setFormFields] = useState({
        firstName: "",
        lastName: "",
        userName: "",
        description: "",
        isTrue: true,
        tiers: "",
        favColour: ""
    })


    function handleChange(event) {
        const {name, value, type, checked} = event.target
        setFormFields(prevState => {
            return {
                ...prevState,
                [name]: type === "checkbox" ? checked : value
            }
        })

    }


    return (
        <form>
            <input 
                type="text" 
                placeholder="First Name" 
                onChange={handleChange} 
                name="firstName" 
                value={formFields.firstName}
                />

            <input 
                type="text" 
                placeholder="Last Name" 
                onChange={handleChange} 
                name="lastName" 
                value={formFields.lastName}
                />

            <input 
                type="text" 
                placeholder="Username" 
                onChange={handleChange} 
                name="userName" 
                value={formFields.userName}
                />

            <textarea 
                placeholder="description"
                onChange={handleChange}
                name="description"
                value={formFields.description}
                />

            <input
                type="checkbox"
                id="isTrue"
                checked={formFields.isTrue}
                onChange={handleChange}
                name="isTrue"
                    />
                <label htmlFor="isTrue">Subscribing</label>

                <select 
                    id="favColour"
                    name="favColour"
                    value={formFields.favColour}
                    onChange={handleChange}
                    >
                    <option value="">-- Choose --</option>
                    <option value="red">Red</option>
                    <option value="blue">Blue</option>
                    <option value="yellow">Yellow</option>
                    <option value="indigo">Indigo</option>
                    <option value="orange">Orange</option>
                    <option value="violet">Violet</option>

                </select>

        </form>
    )
}

Отправка форм

В React элемент button используется для обработки отправки. По умолчанию элемент кнопки имеет тип submit, поэтому мы будем использовать его в нашем коде.

<button>Submit</button>

Нажатие кнопки приведет к тому, что форма вызовет обработчик событий onSubmit. Итак, мы добавляем в нашу форму свойство обработчика событий onSubmit с помощью функции handleSubmit, которую мы создадим.

<form onSubmit={handleSubmit}>

Затем создайте функцию handleSubmit и передайте ей event. В теле функции запустите event.preventDefault, чтобы предотвратить обновление страницы, заставляя React повторно отображать компонент.

function handleSubmit(event) {
        event.preventDefault()
    }

Это весь код, вы можете оформить его так, как хотите.

import React, { useState } from "react"



export default function Form () {
    const [formFields, setFormFields] = useState({
        firstName: "",
        lastName: "",
        userName: "",
        description: "",
        isTrue: true,
        tiers: "",
        favColour: ""
    })


    function handleChange(event) {
        const {name, value, type, checked} = event.target
        setFormFields(prevState => {
            return {
                ...prevState,
                [name]: type === "checkbox" ? checked : value
            }
        })
    }

    function handleSubmit(event) {
        event.preventDefault()
    }

    return (
        <form onSubmit={handleSubmit}>
            <input type="text" 
            placeholder="First Name" 
            onChange={handleChange} 
            name="firstName" 
            value={formFields.firstName}
            />

            <input type="text" 
            placeholder="Last Name" 
            onChange={handleChange} 
            name="lastName" 
            value={formFields.lastName}
            />

            <input type="text" 
            placeholder="Username" 
            onChange={handleChange} 
            name="userName" 
            value={formFields.userName}
            />

            <textarea 
                placeholder="description"
                onChange={handleChange}
                name="description"
                value={formFields.description}
                />

              <input
                    type="checkbox"
                    id="isTrue"
                    checked={formFields.isTrue}
                    onChange={handleChange}
                    name="isTrue"
                    />
                <label htmlFor="isTrue">Subscribing</label>
                <br />


                <fieldset>

                    <legend>Choose Subscription Plan</legend>

                    <input 
                        type="radio"
                        id="tier1"
                        name="tiers"
                        value="tier1"
                        onChange={handleChange}
                        checked={formFields.tiers === "tier1"}
                    />
                    <label htmlFor="tier1">Tier 1</label>
                    <br />
                    <input 
                        type="radio"
                        id="tier2"
                        name="tiers"
                        value="tier2"
                        onChange={handleChange}
                        checked={formFields.tiers === "tier2"}
                    />
                    <label htmlFor="tier2">Tier 2</label>
                    <br />
                    <input 
                        type="radio"
                        id="tier3"
                        name="tiers"
                        value="tier3"
                        onChange={handleChange}
                        checked={formFields.tiers === "tier3"}
                    />
                    <label htmlFor="tier3">Tier 3</label>
                    <br />
                </fieldset>
                <br />

                <label htmlFor="favColour">What is your favourite colour</label>
                <br />

                <select 
                    id="favColour"
                    name="favColour"
                    value={formFields.favColour}
                    onChange={handleChange}
                    >
                    <option value="">-- Choose --</option>
                    <option value="red">Red</option>
                    <option value="blue">Blue</option>
                    <option value="yellow">Yellow</option>
                    <option value="indigo">Indigo</option>
                    <option value="orange">Orange</option>
                    <option value="violet">Violet</option>

                </select>
                <br />
                <br />

                <button>Submit</button>

        </form>
    )
}

На этом мы подошли к концу этого практического руководства.

Заключение

Поздравляем! Теперь вы можете создавать формы в React. Чтобы получить доступ к исходному коду, используемому в этом руководстве, перейдите в репозиторий, чтобы получить его.

Первоначально опубликовано на https://bandojay.hashnode.dev.