React: Obsługa formularzy

Opublikowano: 25.04.2023 - tagi: JavaScript React Formularz

Jak obsługiwać formularze?

Obsługa formularzy w React jest prosta. Istnieją oczywiście biblioteki do przetwarzania danych z formularzy. W tym wpisie podam przykłady, jak ogarnąć formularz bez dodatkowej biblioteki.

Przykłady

Przykład 1 - Pobieranie wartości

import React from 'react';

const App = () => {
    return (
        <>
            <label htmlFor="name">Name:</label>
            <input type="text" id="name" name="name" onChange={(e) => console.log(e.target.value)}/>
        </>
    );
}

Pierwszy przykład pokazuje, jak pobrać dane z danej kontrolki. Żeby, to zrobić należy podpiąć się pod zdarzenie onChange i przekazać funkcję, która pobierze dane.

Przykład 2 - Pobieranie wartości jeszcze raz

import React, { useState } from 'react';

const initFormState = {
    name: '',
    javascript: false,
    java: false,
    swift: false,
}

const App = () => {
    const [formState, setFormState] = useState(initFormState);

    const onChangeHandler = e => {
        const value = e.target.type === 'checkbox' ? e.target.checked : e.target.value;
        setFormState({
            ...formState,
            [e.target.name]: value
        })
    };

    const onSubmitHandler = e => {
        e.preventDefault();
        console.log('formState: ', formState)
    }

    return (
        <>
            <form onSubmit={onSubmitHandler}>
                <label htmlFor="name">Name:</label>
                <input type="text" id="name" name="name" onChange={onChangeHandler} value={formState.name} />
                <fieldset>
                    <legend>Select preferred programming languages</legend>
                    <input type="checkbox" id="javascript" name="javascript" onChange={onChangeHandler} checked={formState.javascript}/>
                    <label htmlFor="javascript">JavaScript</label>
                    <input type="checkbox" id="java" name="java" onChange={onChangeHandler} checked={formState.java}/>
                    <label htmlFor="java">Java</label>
                    <input type="checkbox" id="swift" name="swift" onChange={onChangeHandler} checked={formState.swift}/>
                    <label htmlFor="swift">Swift</label>
                </fieldset>
                <div>
                    <button type="submit">Send</button>
                </div>
            </form>
        </>
    );
}

Można napisać uniwersalną funkcję, która pobierze dane z całego formularza. Spójrz na funkcję onChangeHandler.

Za pomocą linijki kodu:

e.target.value

Możesz pobrać dane prawie ze wszystkich kontrolek. Prawie. Wyjątkiem jest kontrolka typu checkbox. Jeśli masz do czynienia z checkbox użyj:

e.target.checked

Kolejny fragment kodu:

setFormState({
	...formState,
	[e.target.name]: value
})

Odpowiedzialny jest za zaktualizowanie stanu formularza. Żeby to zadziałało, musisz nadać każdej kontrolce formularza nazwę za pomocą atrybutu: name.

Dzięki tak napisanej funkcji onChangeHandler możesz pobrać dane z całego formularza!

Przykład 3 - Wypełnianie formularza danymi

Poniżej przykład jak wypełnić formularz danymi lub go zresetować.

import React, { useState } from 'react';

const initFormState = {
    name: '',
    javascript: false,
    java: false,
    swift: false,
    color: '',
    transport: ''
}

const Form = ({onSubmit, data}) => {
    const [formState, setFormState] = useState(initFormState);

    useEffect(() => {
        setFormState(data);
    }, [data]);

    const onChangeHandler = e => {
        const value = e.target.type === 'checkbox' ? e.target.checked : e.target.value;
        setFormState({
            ...formState,
            [e.target.name]: value
        })
    };

    const onSubmitHandler = e => {
        e.preventDefault();
        onSubmit(formState);
    }

    return (
        <>
            <form onSubmit={onSubmitHandler}>
                <label htmlFor="name">Name:</label>
                <input type="text" id="name" name="name" onChange={onChangeHandler} value={formState.name} />
                <fieldset>
                    <legend>Select preferred programming languages</legend>
                    <input type="checkbox" id="javascript" name="javascript" onChange={onChangeHandler} checked={formState.javascript}/>
                    <label htmlFor="javascript">JavaScript</label>
                    <input type="checkbox" id="java" name="java" onChange={onChangeHandler} checked={formState.java}/>
                    <label htmlFor="java">Java</label>
                    <input type="checkbox" id="swift" name="swift" onChange={onChangeHandler} checked={formState.swift}/>
                    <label htmlFor="swift">Swift</label>
                </fieldset>
                <label htmlFor="color">Select your favorite color</label>
                <select id="color" name="color" onChange={onChangeHandler} value={formState.color}>
                    <option>None selected</option>
                    <option value="red">Red</option>
                    <option value="green">Green</option>
                    <option value="blue">Blue</option>
                </select>
                <fieldset>
                    <legend>Transport</legend>
                    <input type="radio" id="bike" name="transport" value="bike" onChange={onChangeHandler} checked={formState.transport === 'bike'} />
                    <label htmlFor="bike">Bike</label>
                    <input type="radio" id="car" name="transport" value="car" onChange={onChangeHandler} checked={formState.transport === 'car'} />
                    <label htmlFor="car">Car</label>
                    <input type="radio" id="train" name="transport" value="train" onChange={onChangeHandler} checked={formState.transport === 'train'} />
                    <label htmlFor="train">Train</label>
                </fieldset>
                <div>
                    <button type="submit">Send</button>
                </div>
            </form>
        </>
    );
}

const preparedFormState = {
    name: 'Jan Kowalski',
    javascript: false,
    java: false,
    swift: true,
    color: 'green',
    transport: 'bike'
}

const App = () => {
    const [data, setData] = useState(initFormState);

    const onSubmitHandler = formState => {
        console.log('formState: ', formState)
    }

    const onLoadData = () => {
        setData(preparedFormState);
    }

    const onResetForm = () => {
        setData(initFormState);
    }

    return (
        <>
           <Form data={data} onSubmit={onSubmitHandler} />
           <button onClick={onLoadData}>Load data</button>
           <button onClick={onResetForm}>Reset form</button>
        </>
    );
}