REST (HATEOAS) и ReactJS
Я заинтересован в использовании принципа REST HATEOAS для уменьшения бизнес-логики в приложении SPA. В конкретном контексте React, я хотел бы знать, есть ли проблемы, которые делают это непрактичным, и, если нет, какую стратегию следует придерживаться?
Концептуальные примеры использования HATEOAS для удаления бизнес-логики из пользовательского интерфейса:
Я нашел только одну ссылку, которая говорит о том, что React/Flux не совместим со стратегией HATEOAS, и никаких других обсуждений не было. Неужели это невозможно в приложении React/Flux? Этот ТАК пост не получил достаточного внимания. У кого-нибудь есть любимый или рекомендуемый подход для достижения успеха (с Flux или Redux или без него)?
Кто-то привел довольно подробный пример использования HATEOAS в контексте Angular. Я ищу что-то подобное для React.
Лично я представляю тег rel
в ссылках гипермедиа, управляющих отображением компонентов JSX (условный JSX). Это наивно для реального приложения React? Возможно, условно визуализированные компоненты React слишком грубые, чтобы использовать их таким образом?
Я предполагаю, что гиперссылки предоставляются реализацией HAL или иным образом соответствуют соглашению о подаче ATOM (RFC4287).
Ответы
Ответ 1
100% HATEOAS IS совместим с React and Flux, HATEOAS совместим с Angular, HATEOAS совместим с JQuery и даже с vanilla JS.
HATEOAS не накладывает каких-либо технических требований или требований к реализации для потребителя-клиента.
HATEOAS на самом деле просто представляет собой концепцию, для которой вы можете проектировать свой API (вы можете использовать один из нескольких стандартов, хотя HAL)
В принципе, если вы можете вызвать API, вы можете реализовать клиент HATEOAS.
Итак, как туда добраться:
- Шаг 1, как бы вы обычно выполняли вызов API в React? Сделайте это так же.
- Шаг 2, выполните опрос.
- Шаг 3, основанный на ответе, отвечает в пользовательском интерфейсе соответствующим образом.
Например, при вызове порядка api /orders
, я получаю следующий ответ:
{
"_links": {
"self": { "href": "/orders" },
"next": { "href": "/orders?page=2" }
}
}
Из этого я могу заключить, что next
является действительным отношением, и что если я перейду к этому href, я бы фактически получил вторую страницу заказов, поэтому в этом случае в пользовательском интерфейсе отобразится следующая кнопка.
Однако, если бы я получил следующий ответ:
{
"_links": {
"self": { "href": "/orders" },
}
}
Тогда я мог бы сделать вывод, что next
не является корректным отношением, и в моем пользовательском интерфейсе я должен отключить или не отобразить следующую кнопку.
Нет волшебства, это просто изменение мышления, новая парадигма.
Ответ 2
Прежде чем я расскажу о своем наиболее вероятном неправильном/нерелевантном ответе, я просто хочу сообщить вам, что я только что прочитал, что такое HATEOAS. Это предупреждение, из того, что я кратко прочитал, HATEOAS, по-видимому, в основном касается API, рассказывающего вам, как перемещаться по самому себе, предоставляя ссылку на ресурсы, относящиеся к ресурсу, который вы только что запросили.
В этом случае я не вижу причины, по которой вы не можете реализовать динамические url-аякс-вызовы в своих действиях, которые изменят ваше состояние приложения SPA (то есть Redux) на основе того, что вам было предоставлено, вам все равно нужно будет что-то представить государство визуально для всех частей вашего приложения. Здесь грубое полу-псевдо и не очень хорошо продуманное представление о том, что я имею в виду, основанный на вашем примере банковского счета:
// our component file
import React from 'react'
import { makeAWithdrawl } from './actions'
export default React.createClass({
handleClick: function(e) {
e.preventDefault()
makeAWithdrawl(this.props.account.withdraw.href)
},
render: function () {
<div className="account">
<p className="account_number">{this.props.account.accountNumber}</p>
<p className="balance">{this.props.account.balance}</p>
<p><a href={this.props.account.deposit.href}>Deposit</a></p>
{this.props.account.withdraw ? <p><a onClick={this.handleClick}>Withdraw</a></p> : ''}
</div>
}
})
// our actions file
import store from 'store' // our redux store
import axios from 'axios' // an ajax library
export function makeAWithdrawl(url) {
return axios.post(url).then(function(resp){
store.dispatch({
type: 'MAKE_WITHDRAWL',
action: resp.data
}) // do your reducer stuff
})
}
Ваше приложение все еще знает, что он делает в SPA, однако это позволит API направить вас туда, куда вызывать, для каких-либо действий, которые необходимо выполнить. Надеюсь, что это поможет.