Макс Лапшин (levgem) wrote,
Макс Лапшин
levgem

Categories:

Опыт с React, проблемы и т.п.

В процессе развития Flussonic мы подошли к очень интересной схеме работы с конфигурацией сервера.

Схема, которая должна получиться, выглядит следующим образом:
на сервере при чтении текстового файла конфига T появляется эрланговская структура C которую может прочесть любой кусок кода, что бы узнать, какая у него должна быть конфигурация.

Когда админ заходит в админку, из C получается json J (C состоит из бинарей, мапов и чисел, так что здесь должен отрабатывать простой jsx:encode).

Из этого J рендерится вся админка, которая в лучших традициях реакта рисует большой JSON объект через свои вложенные view.



Дальше начинается редактирование конфига. Когда меняется какое-то поле, например source_timeout у стрима, то создается объект Delta, такой что Apply(J, Delta) -> J. Каждое нажатие кнопочки обновляет эту дельту и каждый контрол имеет ручку, спущенную сверху, подергав за которую можно подправить дельту.

Delta имеет такую же структуру, как и J с небольшими ньюансами. Например, если хочется переименовать {"a" : 5} в {"b" : 5}, то дельта будет такой: {"a":null, "b":5}

Здесь есть очевидная проблема с массивами, которую мы решаем так, что считаем массивы атомарным значением. Т.е. {"a" : [5,4,3]} в {"a" : [5,4]} превращается через дельту {"a": [5,4]}

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


Последующие редактирования админки дополняют саму дельту и админу показывается результат приложения этой дельты к загруженному конфигу.

При сохранении дельта отправляется на сервер, там превращается в такую же структуру на эрланге, примеряется к текущему конфигу и результат сохраняется в текстовый формат.


Проблемы



Теперь к неприятному. Есть у нас такое место как опции урла стрима:
{"url" : "rtmp://source/path", "options" : {"key1" : "value1"}}


Когда input привязан к значению элемента по индексу key1, то с его модификацией вопросов нет. Кнопку нажали и появилась дельта: {"options" : {"key1" : "value2"}}

Когда хотим поменять значение key1, то дельта должна уже стать такой:
{"options": {"key1": null, "key2": "value1"}}

и здесь возникают проблемы.

Дело в том, что для того что бы отрендерить все поля, реакту надо указать какой-то уникальный идентификатор строки в списке. Например:

Object.keys(config.options).map(function(k) {
return <div key={k}><input value={k}> <input value={config.options[k]}></div>
});

при этом редактирование самого ключа всё разломает: key поменяется, реакт запустит свою перегенерацию DOM и создаст новый input. Для пользователя это будет выглядеть как потеря фокуса, а по факту это будет создание нового input на том же месте.


Кто-нибудь с похожим сталкивался? Какие есть пути решения?


На данный момент у нас пока такая схема:

1) Создаем контрол для редактирования всего объекта options
2) этот контрол при чтении options трансформирует его в массив [{key: "key1", value: "value1"},...]
3) пока происходит редактирование полей, то меняется лишь стейт этого промежуточного контрола
4) когда происходит blur, тогда формируется пакет изменений и перестраивается стейт этого контрола

Тогда ключом в списке реактовых элементов является просто порядковый номер ключа в объекте (да-да, надеемся на то, что в яваскрипте стабильная нумерация объектов)
Subscribe
  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

  • 16 comments