Иерархия компонентов:
Parent Component: App.js
... Child component: ExampleForm.js
... Child component: SubmittedFormInfo.js
Цель
У меня есть пример формы в дочернем компоненте ExampleForm
для получения ввода названия, url изображения и цены для нового товара. Я хочу, чтобы эта информация немедленно отображалась в другом дочернем компоненте SubmittedFormInfo
, без необходимости обновлять страницу.
Оба этих компонента являются дочерними компонентами App
, но информация не может быть передана напрямую между такими компонентами, как эти. Как мы можем взять информацию из формы, а затем сразу же отобразить ее в другом компоненте?
Прогулка
Этот вопрос зависит от использования функций state и setter, передаваемых в качестве реквизитов каждому из компонентов. Поскольку информация не может быть передана напрямую между родственными компонентами, нам необходимо использовать состояние в родительском компоненте, которое будет передавать информацию каждому из двух компонентов, чтобы данные могли быть отображены.
Компонент приложения
Начните с использования хука useState в компоненте App
и используйте начальное значение пустого объекта, который в конечном итоге будет содержать информацию из нашего примера формы:
function App() {
const [newItem, setNewItem] = useState({})
Нас пока не слишком волнует фактическое значение newItem
. Вместо этого начнем с передачи функции-сеттера setNewItem
компоненту ExampleForm
. Первая цель здесь заключается в том, что мы хотим изменить значение newItem
при отправке формы с помощью переданной функции-сеттера:
<ExampleForm setNewItem={setNewItem}/>
function ExampleForm({ setNewItem }) {
Компонент ExampleForm
Прежде чем двигаться дальше, нам нужно использовать управляемую форму для отслеживания данных, вводимых пользователем. Для простоты объявим три начальных значения в виде пустых строк для каждого поля ввода на форме с помощью хука useState:
function ExampleForm({ setNewItem }) {
const [name, setName] = useState('')
const [image, setImage] = useState('')
const [price, setPrice] = useState('')
Они будут использоваться в качестве значений для каждого ввода в форме примера следующим образом:
<form>
<input type="text" name="name" placeholder="Name" value={name} />
<input type="text" name="image" placeholder="Image URL" value={image} />
<input type="number" name="price" placeholder="Price" value={price} />
<button type="submit">Add Item</button>
</form>
Для управляемых форм каждое изменение, которое пользователь вносит в поле ввода, должно обновлять состояние, чтобы отслеживать информацию, введенную пользователем. Это особенно полезно для немедленного использования информации, например, когда вы хотите, чтобы соответствующие элементы отображались в DOM с помощью строки поиска по мере ввода пользователем. Даже если нам нужна эта информация только при отправке, все равно полезно использовать контролируемую форму. Чтобы сделать эту форму управляемой, начните с объявления трех отдельных функций для обработки изменений в каждом из полей ввода. В каждой функции мы хотим использовать функции-установщики setName
, setImage
и setPrice
из состояния этого компонента. Каждая функция должна обновлять состояние, используя объект события, для доступа к данным о каждой введенной в форму букве:
function handleNameChange(event) {
setName(event.target.value)
}
function handleImageChange(event) {
setImage(event.target.value)
}
function handlePriceChange(event) {
setPrice(event.target.value)
}
Чтобы вызвать эти функции, когда пользователь вводит данные, используйте эти функции в качестве обратных вызовов для событий onChange в каждом из полей ввода формы:
<form>
<input type="text" name="name" placeholder="Name" value={name} onChange={handleNameChange}/>
<input type="text" name="image" placeholder="Image URL" value={image} onChange={handleImageChange}/>
<input type="number" name="price" placeholder="Price" value={price} onChange={handlePriceChange}/>
<button type="submit">Add Item</button></form>
Общая идея заключается в том, что по мере ввода пользователем данных каждая из этих функций будет вызываться для обновления состояния. Поскольку мы используем переменные состояния в качестве входных значений в форме, значения формы будут обновляться по мере обновления состояния с помощью функций-обработчиков. Когда пользователь закончит вводить текст, у нас будет полная информация, доступная для использования в каждой из переменных состояния name
, image
и price
.
Когда пользователь отправляет форму, мы хотим изменить значение newItem, объявленное в App
, используя информацию, введенную пользователем. Мы можем сделать это, вызвав функцию-сеттер setNewItem
, которая была передана компоненту формы в качестве реквизита. Начните с объявления функции handleSubmit, которая должна вызываться, когда пользователь отправляет форму с помощью функции onSubmit в открывающем теге формы. В функции handleSubmit мы хотим создать новый объект, указав пары ключ/значение, используя переменные состояния в качестве каждого значения, следующим образом:
const formData = {
name: name,
image: image,
price: parseInt(price)
}
Затем вызовите setNewItem
, используя объект formData в качестве указанного значения:
setNewItem(formData)
По желанию, мы можем предотвратить обновление страницы и установить значения формы обратно в пустые строки, чтобы получить новые данные от пользователя. Окончательная функция handleSubmit должна выглядеть примерно так:
function handleSubmit(event) {
event.preventDefault();
const formData = {
name: name,
image: image,
price: parseInt(price)
}
setNewItem(formData)
setName('')
setImage('')
setPrice('')
}
Основной строкой кода, на которой следует сосредоточиться, является setNewItem(formData)
. Это обновляет состояние в родительском компоненте App
, что позволяет нам затем передать данные формы в SubmittedFormInfo
как дочерний компонент App
.
Компонент SubmittedFormInfo
Чтобы окончательно отобразить данные формы в нашем приложении, в компоненте App
передайте newItem
как свойство в SubmittedFormInfo
:
<SubmittedFormInfo newItem={newItem}/>
newItem
теперь содержит объект с названием, url изображения и ценой товара, добавленного пользователем. Пусть SubmittedFormInfo
получает реквизит и, по желанию, деструктурирует newItem для более удобного использования информации, содержащейся в объекте newItem.
function SubmittedFormInfo({ newItem }) {
const {name, image, price} = newItem
Все, что осталось сделать, это отобразить в DOM переменные имени, изображения и цены:
return (
<header>
<h2>
Submitted Form Data
</h2>
<p>Name: {name}</p>
<p>Image url: {image}</p>
<p> Price: ${price}</p>
</header>
);
}
Благодаря этому добавлению, после того, как пользователь отправит форму, информация, введенная пользователем, должна автоматически отобразиться в DOM. Это происходит из-за обновления состояния. Поскольку SubmittedFormInfo
зависит от переменной newItem
в состоянии, как только значение newItem
обновится, это заставит компонент SubmittedFormInfo
перерисоваться, немедленно отображая информацию, введенную пользователем.
Заключение
Мы использовали newItem
и его функцию-сеттер для обновления приложения. Мы начали с передачи функции ‘setNewItem’ в ExampleForm
, которая вызывалась, когда пользователь отправлял форму. По мере того как пользователь набирал текст, состояние компонента формы обновлялось, отслеживая значения, введенные пользователем. После отправки формы мы установили значение newItem
на данные, введенные пользователем. Это вызвало обновление состояния newItem
, которое было передано в наш контейнер отображения в качестве свойства. Затем этот компонент повторно отображался при отправке, отображая информацию, введенную пользователем, непосредственно под формой, без необходимости обновлять страницу.