В Hyperapp эффекты (effects) представляют собой способ взаимодействия с внешним миром, не нарушая принципов чистоты функций в основной логике приложения. Эффекты позволяют выполнять асинхронные операции, работать с браузерным API, отправлять сетевые запросы и управлять побочными действиями, не смешивая их с чистым состоянием и обновлением вью.
Эффект в Hyperapp — это объект с обязательными полями:
const effect = {
effect: (dispatch, props) => { /* логика эффекта */ },
// необязательное поле, для идентификации эффекта при повторных вызовах
id: props => props.id,
// аргументы эффекта
props: {...}
};
dispatch и
props. dispatch используется для вызова
действий в приложении, а props передаются при создании
эффекта.Пользовательский эффект создается через функцию-обертку, которая возвращает объект с указанными полями. Пример эффекта для логирования:
const LogEffect = message => ({
effect: (dispatch, props) => {
console.log(props.message);
},
props: { message }
});
Использование эффекта в действии:
const actions = {
logMessage: message => state => [
state,
LogEffect(message)
]
};
При вызове actions.logMessage("Привет Hyperapp!")
сообщение будет выведено в консоль.
Hyperapp поддерживает асинхронные операции в эффектах через
async/await или промисы. Пример запроса к API:
const FetchEffect = url => ({
effect: async (dispatch, props) => {
try {
const response = await fetch(props.url);
const data = await response.json();
dispatch({ type: "fetchSuccess", data });
} catch (error) {
dispatch({ type: "fetchError", error });
}
},
props: { url }
});
Эффект вызывается из действия:
const actions = {
loadData: url => state => [
state,
FetchEffect(url)
],
fetchSuccess: data => state => ({ ...state, data }),
fetchError: error => state => ({ ...state, error })
};
Для повышения читаемости и повторного использования часто создаются фабрики эффектов, возвращающие готовые объекты с параметрами:
const DelayEffect = (ms, action) => ({
effect: (dispatch) => {
setTimeout(() => dispatch(action), ms);
},
id: () => ms
});
Это позволяет управлять эффектами по идентификатору, предотвращая их дублирование при повторных вызовах с одинаковыми параметрами.
Hyperapp позволяет возвращать массив эффектов из одного действия:
const actions = {
init: () => state => [
state,
[
FetchEffect("/api/data"),
LogEffect("Инициализация завершена")
]
]
};
Каждый элемент массива будет обработан независимо, что упрощает управление несколькими побочными операциями.
Иногда требуется, чтобы эффект хранил состояние между вызовами. Для этого можно использовать замыкания внутри функции эффекта:
const CounterEffect = () => {
let count = 0;
return {
effect: () => {
count += 1;
console.log("Вызвано раз:", count);
},
id: () => "counter"
};
};
Такой подход полезен для таймеров, локальных кэшей и других случаев, когда требуется внутреннее отслеживание.
state только через
dispatch.id для
повторяющихся эффектов, чтобы избежать нежелательного дублирования.Эффекты Hyperapp легко интегрируются с внешними библиотеками и API:
const LocalStorageEffect = key => ({
effect: (dispatch, props) => {
const value = localStorage.getItem(props.key);
dispatch({ type: "loadFromStorage", value });
},
props: { key }
});
В результате можно реализовать сохранение состояния, взаимодействие с IndexedDB, WebSocket, или любыми другими асинхронными интерфейсами без нарушения принципов функционального программирования.
Эффекты Hyperapp создают мощный инструмент для построения реактивных приложений, позволяя отделять чистую логику от побочных действий, управлять асинхронными процессами и упрощать поддержку кода.