LINUX.ORG.RU

React.js: DumbRelay как замена Relay/GraphQL

 ,


0

1

Всем привет! Недавно на новой работе начали использовать React.js, и всё было хорошо, пока наш тимлид не решил подключить к нему Relay, который идёт только в связке с языком запросов GraphQL. Там всё стильно, модно, молодёжно, и основная идея — в декларативной привязке данных к компонентам. Но, важно: этим технологиям около полугода, на сайте GraphQL написано, что версия продукта — черновая, и что всё может кардинально измениться.

Не желая поддаваться хипстерским тенденциям, я решил написать что-то простое, использующее тот же декларативный подход, но не такое перегруженное, и с большей свободой в выборе источников данных (вместо запросов — произвольные функции, возвращающие данные через callback). В планах — добавить внутренний механизм AJAX-запросов (или, если есть удобная библиотека (не jQuery), подскажите мне, пожалуйста).

К счастью, на внедрение Relay/GraphQL у тимлида не хватает времени, так что команда начинает пользоваться моим велосипедом, и, надеюсь, это более правильное решение, чем тащить в серьёзный проект огромный сырой фреймворк.

Короче, вот код: https://github.com/xenohunter/DumbRelay. Надеюсь, пригодится кому-то ещё.

P.S. Предполагаю, что не всем интересно читать README на английском, поэтому под катом ниже — небольшой пример.

import DumbRelay from 'dumb-relay';

class MyList extends Component {
  render() {
    // Данные хранятся в this._data
    var clients = this._data['clients'],
        list = clients.map(function (client) {
          return (<li>{client.name}</li>);
        });
    return(<ul>{list}</ul>);
  }
}

DumbRelay.link(MyList, {
  clients: {
    // Источник данных
    source: api.getClients,

    // Обновление данных каждые 5 секунд
    rate: 5000,

    // Можно пропустить данные через pipeline из фильтров
    pipe: [
      function (data, callback) {
        // Например, показать только VIP-клиентов
        data = data.filter((client) => client.isVIP());
      }
    ]
  }
});

P.P.S. Код не залезает под кат, простите.

P.P.P.S. Подсветку кода убрал специально, так как она сломалась об Harmony.

если есть удобная библиотека (не jQuery), подскажите мне, пожалуйста

А почему, собственно, не jQuery? А то я просто нубас, и для меня это звучит как «если есть удобный способ поесть (не ртом), подскажите мне, пожалуйста».

kosc
()
Ответ на: комментарий от kosc

Ради одного AJAX'а не хочется всю либу тянуть. То есть, лишняя зависимость на сколько там сейчас Кб — это совсем не здорово. Не все же в проектах jQuery используют, а уж особенно в связке с React'ом.

Для webpack есть такой вариант:

var $ = require('jquery/src/core');
require('jquery/src/ajax');
require('jquery/src/ajax/xhr');
Но он не поддерживается в синтаксисе ES6, и это не сработает, если просто пакет из npm взять, без колдунств сборщика.

xenohunter
() автор топика
Ответ на: комментарий от xenohunter

Но он не поддерживается в синтаксисе ES6

А зачем вообще тащить ES6, ведь нет пока полной поддержки. Не проще ли его не использовать?

aboutcard
()
Ответ на: комментарий от aboutcard

Почти всё, что связано с React, написано в ES6. В любом случае, Babel компилирует код для IE8+ и остальных браузеров.

xenohunter
() автор топика

У тебя совсем не про Relay/GraphQL библиотека, лучше уж просто что-то флесообразное. В чем суть локальности зависимостей от данных, если они будут только у +-рутового компонента?

ЗЫ: forceUpdate и сайдэффекты в render() - это победа :)

zz ★★★★
()
Последнее исправление: zz (всего исправлений: 1)
Ответ на: комментарий от zz

Ну, визуально привязка данных напоминает, потому и упомянул их.

В чем суть локальности зависимостей от данных, если они будут только у +-рутового компонента?

Не уверен, что понял. Сделать так, чтобы данные были доступны всем детям компонента, к которому они привязываются?

ЗЫ: forceUpdate и сайдэффекты в render() - это победа :)

Ну, сайдэффекты - только в test/, а вот от forceUpdate я бы и рад отказаться, но не знаю, чем это заменить.

А вообще, спасибо за дельный отзыв.

xenohunter
() автор топика
Ответ на: комментарий от xenohunter

Сделать так, чтобы данные были доступны всем детям компонента, к которому они привязываются

Value proposition релея в том что если у тебя список юзеров например и из него рендерится 15 компонентов, каждый из которых хочет свой набор полей у юзера - это будет один запрос который вернет только те поля которые реально хотят компоненты.

Ну, сайдэффекты - только в test/, а вот от forceUpdate я бы и рад отказаться, но не знаю, чем это заменить.

Ну так запрос в апи не сайдэффект? forceUpdate в рендере - это бесконечный цикл, потому что он сам вызывает рендер. За данными надо ходить в componentWillMount или каком-нибудь другом подходящем хуке, из него сделаешь setState и все перерендерится.

zz ★★★★
()
Последнее исправление: zz (всего исправлений: 2)
Ответ на: комментарий от zz

Чего нет, того нет. Для таких гибких запросов нужно по-любому что-то на сервере поднимать. Я же делаю так, чтобы можно было к любому API удобно подключаться. Подумаю, как бы это обозвать чуть иначе в описании. Что-то в голову NoRelay приходит, лол.

forceUpdate в рендере

Запрос же не из render идёт. Запросы как раз в componentWillMount стартуют. В render — только map массивов с данными. В эти массивы данные поступают из binding'ов, которые вызваны либо из componentWillMount, либо по таймауту.

xenohunter
() автор топика
Ответ на: комментарий от xenohunter

Я про твой пример обычного реакт кода в ридми, который не только не обычный, но и бесконечный цикл.

zz ★★★★
()
Ответ на: комментарий от xenohunter

Но если запрос асинхронный оно не будет работать :) Тебе вообще не нужно дергать forceUpdate нигде, в тч в DumbRelay, храни стейт как нормальные люди :), this.setState все перерендерит, shouldComponentUpdate не будет сломан и тд

zz ★★★★
()
Ответ на: комментарий от zz

Спасибо тебе, принял во внимание. И да, мне уже посоветовали переписать всё как класс, от которого будет наследовать каждый конкретный компонент. Тогда да, можно будет в this.state.data хранить данные, и написать это красиво.

xenohunter
() автор топика
Ответ на: комментарий от xenohunter

Щас модно композиция vs наследование, то есть все делают свои компоненты для работы с данными, которые враппят компоненты которые только рендерят, аля https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0#.mxaic...

Можешь посмотреть как в redux выглядит api http://redux.js.org/docs/basics/UsageWithReact.html

zz ★★★★
()
Ответ на: комментарий от zz

Smart and Dumb читал уже, Redux посмотрел, там всё с большим уровнем абстракции. Я что-то уже перегорел пилить DumbRelay, ибо в проект, над которым работаю, всё же втащили Relay/GraphQL, а сам я React больше использовать всё равно нигде не буду.

xenohunter
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.