React, Flux, состояние и магазины

Я считаю, что примера приложения todo flux немного не хватает, поэтому я пытаюсь разобраться в этом, разрабатывая приложение для обучения и экспериментов.

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

Исходя из этого у меня есть 3 магазина:

  • Магазин фруктов
  • КорзинаМагазин
  • AppStateStore — для отслеживания последнего нажатия и последнего перетаскивания фруктов

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

Основной компонент AppView прослушивает события изменения как из FruitStore, так и из AppStateStore и выполняет повторную визуализацию.

Мои вопросы:

  • Это хороший подход для этого сценария?
  • Должен ли AppView прослушивать несколько магазинов? Как мне предотвратить рендеринг AppView несколько раз подряд? Прямо сейчас, когда фрукт был перемещен, и FruitStore, и AppStateStore запускают события change, вызывая два рендеринга подряд.
  • В статье Flux на сайте React показано представление, отправляющее объект действия (например, AppDispatcher.dispatch(TodoActions.updateText())) ), но было бы лучше, если бы действие отправлялось само (например, просто FruitActions.moveBasket() ), а AppView не знали о AppDispatcher?
  • В настоящее время только AppView прослушивает хранилища, но должны ли отдельные компоненты Fruit прослушивать AppStateStore, чтобы повторно отображать только себя, если они должны быть выделены?
  • Есть ли более полный пример архитектуры Flux или что-то подобное?

person user3687035    schedule 29.05.2014    source источник
comment
Вы где-нибудь публиковали код примера?   -  person Lucas    schedule 29.05.2014
comment
Я проголосовал слишком широко, потому что на самом деле слишком много вопросов для одного вопроса. Я думаю, что это должно быть немного более сосредоточенным.   -  person demongolem    schedule 29.05.2014
comment
@demongolem: Спасибо за советы. Я буду иметь это в виду в будущем.   -  person user3687035    schedule 30.05.2014
comment
@ Лукас: Не сейчас   -  person user3687035    schedule 30.05.2014
comment
Вы пропустили один термин из своего названия — Redux, который является самой известной реализацией потока для реагирования.   -  person RBT    schedule 12.05.2017


Ответы (2)


  • Подход звучит довольно солидно. Я бы создал совершенно разные действия для каждого взаимодействия, например. FruitClicked и FruitDragged могут быть действиями, и магазины будут следить за теми, кто им небезразличен.
  • AppView должен прослушивать все хранилища, из которых он получает данные. Если вы вызываете setState более одного раза за один и тот же тик, React интеллектуально объединит их, так что на самом деле вы не выполняете рендеринг более одного раза.
  • В статье на сайте React говорится об действиях, которые отправляются сами по себе в Создание семантических действий. В блоке кода на несколько прокруток вверх по странице вы можете увидеть код:

    _onDestroyClick: function() { 
      TodoActions.destroy(this.props.todo.id); 
    } 
    
  • #P2#
    #P3#
    #P4#
    #P5#
  • Если вас интересует архитектура Flux, вас может заинтересовать Fluxxor (отказ от ответственности: это написал я), который ( надеюсь) помогает создать приложение на основе потока. У него есть диспетчер, который немного более надежен, и несколько других изменений (например, неглобальные хранилища/действия, примеси React), которые во многих случаях немного упрощают работу.
person Michelle Tilley    schedule 29.05.2014
comment
Спасибо за разъяснения. Я посмотрел на Fluxxor до того, как начал это, и он выглядит великолепно, но я хотел понять мельчайшие детали, прежде чем оставить его в библиотеке. Спасибо, что поправили меня и в «Семантических действиях». Я явно неправильно это понял. Вы говорите о том, что React объединяет действия в один тик; означает ли это, что React использует rAF или что-то подобное, когда есть изменения? - person user3687035; 30.05.2014
comment
@user3687035 user3687035 Я не уверен в этом на 100%, но я думаю, что React просто рендерит на следующем тике (например, через setTimeout) по умолчанию; есть стратегия RAF в репозитории/кодовой базе React , но я не думаю, что он используется в данный момент. - person Michelle Tilley; 30.05.2014
comment
Обновление: React автоматически объединяет рендеры после обработки синтетического события (например, onClick); если вы меняете состояние асинхронно, например. в обработчике setTimeout или Ajax он будет выполнять пакетные обновления только в том случае, если вы оберните изменения состояния в React.addons.batchedUpdates (добавлено в версии 0.12.0). - person Michelle Tilley; 07.02.2015
comment
Как насчет вопроса о множественных рендерах? Это проблема? Насколько я понимаю, из-за различия DOM компонент DOM будет отображаться, если в компоненте React есть фактическое изменение. Таким образом, внесение изменений не приведет к автоматическому повторному рендерингу чего-либо. - person Josef.B; 28.03.2015

Трудно сказать, хорош ли подход, не разобравшись в приложении.

Однако мне кажется, что щелчок по фрукту должен обрабатываться FruitStore. То есть плод приобрел активное состояние, стал перетаскиваемым. Если это каким-то образом повлияет на приложение в целом, то, возможно, это вызовет изменение и в AppStateStore. Точно так же перемещение фруктов из одной корзины в другую похоже на домен BasketStore.

Я представляю, как FruitStore содержит частную структуру данных, подобную этой:

var _fruit = {
  1234: {
    id: '1234',
    type: 'apple',
    active: false
  },
  2345: {
    id: '2345',
    type: 'orange',
    active: false
  },
  3456: {
    id: '3456',
    type: 'apple',
    active: false
  }
};

и я представляю себе BasketStore с частной структурой данных, которая выглядит так:

var _baskets = {
  4321: {
    id: '4321',
    name: 'Josephine\'s Basket',
    fruitIDs: [
      1234,
      2345
    ]
  },
  5432: {
    id: '5432',
    name: 'Harold\'s Basket',
    fruitIDs: [
      3456
    ]
  }
};

Таким образом, фруктовое «активное» состояние управляется FruitStore, а содержимое корзин управляется BasketStore.

Таким образом, AppView может прослушивать оба хранилища, если это хорошо работает для вашего приложения. И, как упоминалось выше, повторный вызов метода render() требует очень мало затрат. Это не затрагивает DOM при каждом вызове — это одна из самых сильных сторон React. Вместо этого React будет разумно группировать вызовы и обновлять только «грязные» части DOM, если они существуют.

Но, возможно, вы захотите, чтобы корзины стали представлениями контроллера. Если вы решите сделать свои фрукты представлениями контроллера, обязательно очистите прослушиватели в componentWillUnmount(), так как перемещение фруктов из корзины в корзину может потребовать их уничтожения и воссоздания. Я думаю, что прослушивание на уровне корзины имеет больше смысла, но опять же, я не очень хорошо понимаю ваше приложение.

Чтобы ответить на ваш последний вопрос:

Есть ли более полный пример архитектуры Flux или что-то подобное?

Инженеры Facebook сейчас работают над более сложным примером приложения, в котором будет продемонстрировано использование функции waitFor() и постоянного хранилища на стороне сервера. Мы надеемся выпустить это в ближайшее время.

person fisherwebdev    schedule 05.07.2014