Stimulus не подменяет собой слой работы с сервером и не навязывает
конкретный способ отправки запросов. Он концентрируется на связывании
поведения с HTML, а обработка ответов сервера строится поверх
стандартных браузерных API: fetch,
XMLHttpRequest, FormData, событий DOM и
HTTP-статусов. Такой подход позволяет выстраивать предсказуемую
архитектуру без скрытой магии.
Контроллер Stimulus обычно отвечает за три задачи:
Контроллер Stimulus представляет собой класс, методы которого
вызываются через действия (data-action). Обработка ответа
сервера почти всегда начинается с асинхронного метода.
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
async submit(event) {
event.preventDefault()
const response = await fetch("/endpoint")
const data = await response.json()
this.handleSuccess(data)
}
handleSuccess(data) {
// обновление интерфейса
}
}
Ключевые особенности:
Ответ сервера не всегда означает успешный результат. Stimulus-контроллер должен явно анализировать статус ответа.
const response = await fetch(url)
if (!response.ok) {
this.handleError(response)
return
}
Типичные сценарии:
Рекомендуется разделять обработку:
fetch);try {
const response = await fetch(url)
if (!response.ok) {
const errorData = await response.json()
this.showValidationErrors(errorData)
return
}
const data = await response.json()
this.updateView(data)
} catch (error) {
this.showNetworkError()
}
JSON — наиболее распространённый формат ответов. Stimulus не добавляет надстроек поверх парсинга, поэтому важно явно контролировать структуру данных.
updateView(data) {
this.messageTarget.textContent = data.message
}
Рекомендуемые практики:
Сервер может возвращать готовые HTML-фрагменты. Это особенно характерно для приложений с server-side rendering.
const html = await response.text()
this.containerTarget.innerHTML = html
При таком подходе:
Важно учитывать, что замена innerHTML уничтожает старые
DOM-узлы и связанные с ними состояния.
Stimulus часто используется для перехвата отправки форм.
async submit(event) {
event.preventDefault()
const formData = new FormData(this.element)
const response = await fetch(this.element.action, {
method: this.element.method,
body: formData
})
}
Варианты обработки ответа:
Пример обработки ошибок валидации:
if (response.status === 422) {
const errors = await response.json()
this.renderErrors(errors)
}
Stimulus-контроллер удобно использовать для управления визуальными состояниями.
async load() {
this.element.classList.add("loading")
try {
const response = await fetch(this.urlValue)
const data = await response.json()
this.render(data)
} finally {
this.element.classList.remove("loading")
}
}
Типичные состояния:
Эти состояния выражаются через:
Stimulus позволяет хранить значения, связанные с сервером, в
values.
static values = {
url: String
}
Это позволяет:
Иногда ответ сервера влияет не на разметку, а на состояние приложения:
if (data.redirect) {
window.location.href = data.redirect
}
Stimulus в таких сценариях выступает как связующее звено между серверной логикой и браузерным поведением.
Ответ сервера может транслироваться в виде кастомного события.
this.element.dispatchEvent(
new CustomEvent("request:success", { detail: data })
)
Преимущества:
Контроллер не должен предполагать корректность ответа сервера.
Рекомендуемые меры:
try/catch вокруг асинхронного кода;if (!data || typeof data !== "object") {
this.showUnexpectedResponse()
}
При использовании Turbo:
Turbo Stream;В таких случаях контроллер:
turbo:submit-end);Stimulus не диктует шаблон работы с сервером, но создаёт строгую и прозрачную рамку, внутри которой обработка ответов сервера остаётся управляемой, тестируемой и легко расширяемой.