Подтвердить что ты не робот

Реакт, флюс, состояние и магазины

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

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

На основании этого у меня есть 3 магазина:

  • FruitStore
  • BasketStore
  • AppStateStore - отслеживать последний щелчок и последний вытащенный плод

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

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

Мои вопросы:

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

Ответ 1

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

    _onDestroyClick: function() { 
      TodoActions.destroy(this.props.todo.id); 
    } 
    
  • В статье также рассказывается о том, какие компоненты должны прослушивать магазины в Прослушивание изменений с помощью Controller-View:

    Нам нужен компонент React рядом с верхней частью нашей иерархии компонентов для прослушивания изменений в хранилище. В более крупном приложении у нас будет больше этих компонентов для прослушивания, возможно, для каждого раздела страницы. В Facebook Ads Creation Tool у нас есть многие из этих представлений, похожих на контроллер, каждый из которых соответствует определенному разделу пользовательского интерфейса. В Lookback Video Editor у нас было только два: один для анимированного предварительного просмотра и один для интерфейса выбора изображения.

    и

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

  • Если вас интересует архитектура потока, вас может заинтересовать Fluxxor (отказ от ответственности: я написал его), который ( надеюсь) помогает создать приложение на основе потока. В нем есть диспетчер, который немного более прочен и несколько других изменений (например, неглобальных магазинов/действий, React mixins), чтобы во многих случаях сделать вещи немного легче.

Ответ 2

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

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

Я представляю, что 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\ Basket',
    fruitIDs: [
      1234,
      2345
    ]
  },
  5432: {
    id: '5432',
    name: 'Harold\ Basket',
    fruitIDs: [
      3456
    ]
  }
};

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

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

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

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

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

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