Привет, мир!
Когда мы работаем с формами в React, мы можем столкнуться с проблемой, из-за которой мы не сможем вводить текст в поле ввода/текстовое поле, если установлено свойство value
. Я бы показал, в чем проблема и как я ее исправил.
Сценарий
Требование
У меня есть API, для которого потребуются три поля, а именно электронная почта, имя и сообщение, которые необходимо передать в теле API. В пользовательском интерфейсе мы будем получать эти значения в поле ввода или текстовой области и будем использовать кнопку для запуска вызова API.
Структура, ожидаемая в API, выглядит примерно так:
{ "email": "[email protected]", "name": "Test", "message": "Hi, this is a test message." }
Выполнение
В приложении React я создал компонент с двумя полями ввода для получения name
и email
, текстовой областью для получения message
и кнопкой для запуска вызова API и отправки трех значений. Вот как выглядел компонент:
import { useState } from "react"; import callApi from "../axios/axios"; import "./contact.scss"; const Contact = () => { const payloadInitial = { sender: "", email: "", message: "", }; const initialClass = "form-input"; const [payload, setPayload] = useState(payloadInitial); // Captures Sender name const setName = (name) => { const temp = payload temp.sender = name setPayload(temp) }; // Captures Email const setEmail = (email) => { const temp = payload temp.email = email setPayload(temp) }; // Captures Message const setMessage = (message) => { const temp = payload temp.message = message setPayload(temp) checkCanSend(); }; // Triggers API call on button click const sendMessage = (evt) => { evt.preventDefault(); callApi .post("/email", payload) .then((res) => { console.log("Response: ", res) }) .catch((err) => { console.error("Something went wrong: ", err) }); }; return ( <div className="form-container"> <h2 className="form-title">Write to me</h2> <div className="form-container"> <!--Input to get sender name--> <label>Your Name</label> <input type={"text"} aria-label="Your Name" value={payload.sender} onChange={(e) => setName(e.target.value)} ></input> <!--Input to get sender email--> <label>Your Email</label> <input type={"email"} aria-label="Your Email" value={payload.email} onChange={(e) => setEmail(e.target.value)} ></input> <!--Textbox to get the message--> <label>Type in your message</label> <textarea rows={8} value={payload.message} onChange={(e) => setMessage(e.target.value)} ></textarea> <!--Button to trigger API call--> <button onClick={(e) => sendMessage(e)} className="send-button"> Send Message </button> </div> </div> ); }; export default Contact;
В приведенном выше компоненте мы прослушиваем изменение полей ввода, используя событие onChange
, и устанавливаем новые значения в состояние payload
.
Проблема
Приведенный выше код вызывал проблему, когда я не мог ввести более одного символа.
Решение
Решение проблемы таково: в функции onClick вместо сохранения состояния во временной переменной, изменения значения во временной переменной и установки временной переменной в состояние, мы должны обновить состояние напрямую.
В нашем случае рассмотрим функцию setName
. Функция должна быть изменена следующим образом:
const setName = (name) => { setPayload((prev) => ({ ...prev, sender: name, })); checkCanSend(); }
Теперь состояние обновляется напрямую, без каких-либо временных переменных.
Теперь мы можем печатать в поле ввода.
Окончательный код будет таким:
import { useState } from "react"; import callApi from "../axios/axios"; import "./contact.scss"; const Contact = () => { const initialClass = "form-input"; const [payload, setPayload] = useState(payloadInitial); // Captures Sender name const setName = (name) => { setPayload((prev) => ({ ...prev, sender: name, })); checkCanSend(); }; // Captures Email const setEmail = (email) => { setPayload((prev) => ({ ...prev, email, })); checkCanSend(); }; // Captures Message const setMessage = (message) => { setPayload((prev) => ({ ...prev, message, })); checkCanSend(); }; // Triggers API call on button click const sendMessage = (evt) => { evt.preventDefault(); callApi .post("/email", payload) .then((res) => { console.log("Response: ", res) }) .catch((err) => { console.error("Something went wrong: ", err) }); }; return ( <div className="form-container"> <h2 className="form-title">Write to me</h2> <div className="form-container"> <!--Input to get sender name--> <label>Your Name</label> <input type={"text"} aria-label="Your Name" value={payload.sender} onChange={(e) => setName(e.target.value)} ></input> <!--Input to get sender email--> <label>Your Email</label> <input type={"email"} aria-label="Your Email" value={payload.email} onChange={(e) => setEmail(e.target.value)} ></input> <!--Textbox to get the message--> <label>Type in your message</label> <textarea rows={8} value={payload.message} onChange={(e) => setMessage(e.target.value)} ></textarea> <!--Button to trigger API call--> <button onSubmit={(e) => sendMessage(e)} className="send-button"> Send Message </button> </div> </div> ); }; export default Contact;
Надеюсь, что это решение поможет решить проблему «Невозможно ввести текст в поле ввода». С нетерпением ждем ваших отзывов. Спасибо!
Первоначально опубликовано на https://sriram23.hashnode.dev.