Hyperapp — это минималистичный фронтенд-фреймворк, основанный на
концепции функционального подхода к управлению состоянием и виртуального
DOM. Несмотря на компактность ядра, Hyperapp позволяет эффективно
работать с внешними API, включая REST и GraphQL, через асинхронные
эффекты (effects) и действия (actions).
В Hyperapp эффект — это функция, которая выполняет побочные действия, такие как сетевые запросы. Эффекты не изменяют состояние напрямую, а получают состояние и вызывают действие, которое уже его обновляет. Основная структура эффекта:
const fetchEffect = (url, action) => (state, actions) => {
fetch(url)
.then(res => res.json())
.then(data => actions[action](data))
.catch(err => console.error(err));
};
В примере выше fetchEffect получает URL и имя действия,
которое будет вызвано после получения данных.
Для работы с REST API часто используется комбинация эффектов и
действий. Состояние (state) хранит данные, полученные с
сервера, а действия обрабатывают успешные или ошибочные ответы.
Пример работы с REST API:
const state = {
users: [],
loading: false,
error: null
};
const actions = {
fetchUsers: () => (state, actions) => {
actions.setLoading(true);
fetchEffect('https://jsonplaceholder.typicode.com/users', 'setUsers')(state, actions);
},
setUsers: (users) => ({ users, loading: false }),
setLoading: (loading) => ({ loading }),
setError: (error) => ({ error, loading: false })
};
В этом примере:
fetchUsers запускает асинхронный эффект;setUsers обновляет состояние после получения
данных;setLoading и setError управляют
индикатором загрузки и обработкой ошибок.GraphQL требует отправки запросов методом POST с
JSON-телом запроса. В Hyperapp структура остается аналогичной REST:
эффект делает запрос, действие обновляет состояние.
Пример запроса к GraphQL:
const graphqlEffect = (query, variables, action) => (state, actions) => {
fetch('https://graphql.example.com', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ query, variables })
})
.then(res => res.json())
.then(data => actions[action](data.data))
.catch(err => console.error(err));
};
const state = {
posts: [],
loading: false
};
const actions = {
fetchPosts: () => (state, actions) => {
actions.setLoading(true);
const query = `
query {
posts {
id
title
content
}
}
`;
graphqlEffect(query, {}, 'setPosts')(state, actions);
},
setPosts: (posts) => ({ posts, loading: false }),
setLoading: (loading) => ({ loading })
};
Особенности GraphQL-запросов:
query описывает, какие данные нужны;variables позволяют передавать динамические
параметры;Для поддержания отзывчивого интерфейса важно отслеживать процесс загрузки и ошибки:
const actions = {
fetchData: () => (state, actions) => {
actions.setLoading(true);
fetchEffect('https://api.example.com/data', 'setData')(state, actions);
},
setData: (data) => ({ data, loading: false, error: null }),
setError: (error) => ({ error, loading: false }),
setLoading: (loading) => ({ loading })
};
Индикаторы загрузки можно связать с state.loading, а
ошибки — с state.error. Это позволяет создавать
динамическое отображение состояния запросов.
В реальных приложениях часто нужно запускать несколько запросов одновременно. Hyperapp позволяет комбинировать эффекты через массивы действий:
const actions = {
fetchAllData: () => [
(state, actions) => fetchEffect('/users', 'setUsers')(state, actions),
(state, actions) => fetchEffect('/posts', 'setPosts')(state, actions)
]
};
Каждый эффект вызывается с текущим состоянием и набором действий, что позволяет гибко управлять несколькими источниками данных.
Для повышения производительности можно:
state и использовать их
повторно;loading,
error, data) для удобного управления
интерфейсом.Эти подходы позволяют эффективно интегрировать Hyperapp с любыми внешними API, сохраняя минималистичность фреймворка, но при этом реализуя современные стандарты асинхронной работы с данными.