2015-07-26 7 views
11

Я только начинаю использовать флюс (с сокращением на данный момент), и мне интересно, как должны обрабатываться отношения.
Для примера мы можем использовать Trello, у которого есть доски с колонками, которые содержат карты.Как обрабатывать отношения «один ко многим» в магазинах Flux

Один из подходов состоит в том, чтобы иметь один магазин/редуктор для плат и иметь все данные в нем, но это означает некоторые очень жирные магазины, так как они должны были содержать все действия для столбцов и карточек.

Другой подход, который я видел, заключается в разделении вложенных ресурсов, например, в BoardStore, ColumnStore и CardStore и использовании их идентификаторов в качестве ссылки.

Вот пример того, где я немного смущен: у вас может быть создатель действия, называемый addCard, который делает запрос на сервер, чтобы создать карту со всеми данными. Если вы делаете оптимистичное обновление, вы бы создали объект карты в одном из своих хранилищ раньше, но вы не сможете узнать идентификатор, который будет иметь, пока вы не вернете запрос.

Так короче:

  • Обжиг addCard
  • addCard делает запрос, в то же время вы возвращаете действие типа ADD_CARD_TEMP
  • вы получаете запрос и возвращает действие типа ADD_CARD где магазин/редуктор изменяет идентификатор.

Есть ли рекомендуемый способ борьбы с этим делом? Вложенный магазин/редукторы выглядят немного глупыми для меня, но в противном случае вы оказываетесь в очень сложных магазинах, поэтому на самом деле это выглядит как компромисс.

ответ

7

Да, использование идентификаторов в нескольких магазинах, похожих на реляционную базу данных, - это способ сделать это правильно.

В вашем примере предположим, что вы хотите оптимистично поместить новую карту в конкретный столбец и что карта может быть только в одном столбце (одна колонка для многих карт).

Карты в вашем CardStore может выглядеть следующим образом:

_cards: { 
    'CARD_1': { 
    id: 'CARD_1', 
    columnID: 'COLUMN_3', 
    title: 'Go to sleep', 
    text: 'Be healthy and go to sleep on time.', 
    }, 
    'CARD_2': { 
    id: 'CARD_2', 
    columnID: 'COLUMN_3', 
    title: 'Eat green vegetables', 
    text: 'They taste better with onions.', 
    }, 
} 

Обратите внимание, что я могу сослаться на карту с помощью идентификатора, и я также могу получить идентификатор в пределах объекта. Это позволяет мне иметь такие методы, как getCard(id), а также иметь возможность извлекать идентификатор определенной карты в пределах слоя вида. Таким образом, у меня может быть метод deleteCard(id), который вызывается в ответ на действие, потому что я знаю идентификатор в представлении.

Внутри магазина карт у вас будет getCardsByColumn(columnID), что будет простой картой над объектами карты, и это создаст массив карт, которые вы могли бы использовать для визуализации содержимого столбца.


Что касается механики оптимистических обновлений, и как использование идентификаторов влияет на его:

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

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

Так у вас есть три действия:

  1. инициирует запрос
  2. ручки успех
  3. ответ Ручка

В ответ на действие, которое инициирует запрос, ваш магазин получает Client- side id и создает запись.

В ответ на успех/ошибку ваш магазин снова получает идентификатор на стороне клиента и либо изменяет запись как подтвержденную запись с реальным идентификатором, либо вместо этого откатывает запись. Вы также хотели бы создать хороший UX вокруг этой ошибки, например, повторить попытку пользователя.

Пример код:

// Within MyAppActions 
cardAdded: function(columnID, title, text) { 
    var clientID = this.createUUID(); 
    MyDispatcher.dispatch({ 
    type: MyAppActions.types.CARD_ADDED, 
    id: clientID, 
    columnID: columnID, 
    title: title, 
    text: text, 
    }); 
    WebAPIUtils.getRequestFunction(clientID, "http://example.com", { 
    columnID: columnID, 
    title: title, 
    text: text, 
    })(); 
}, 

// Within WebAPIUtils 
getRequestFunction: function(clientID, uri, data) { 
    var xhrOptions = { 
    uri: uri, 
    data: data, 
    success: function(response) { 
     MyAppActions.requestSucceeded(clientID, response); 
    }, 
    error: function(error) { 
     MyAppActions.requestErrored(clientID, error); 
    }, 
    }; 
    return function() { 
    post(xhrOptions); 
    }; 
}, 

// Within CardStore 
switch (action.type) { 

    case MyAppActions.types.CARD_ADDED: 
    this._cards[action.id] = { 
     id: action.id, 
     title: action.title, 
     text: action.text, 
     columnID: action.columnID, 
    }); 
    this._emitChange(); 
    break; 

    case MyAppActions.types.REQUEST_SUCCEEDED: 
    var tempCard = this._cards[action.clientID]; 
    this._cards[action.id] = { 
     id: action.id, 
     columnID: tempCard.columnID, 
     title: tempCard.title, 
     text: tempCard.text, 
    }); 
    delete this._cards[action.clientID]; 
    break; 

    case MyAppActions.types.REQUEST_ERRORED: 
    // ... 
} 

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

+0

Спасибо за ответ. Извините, если я не был чист, но мой вопрос был больше о том, как организовать хранилище, и я использовал оптимистическое обновление в качестве примера возможных проблем ссылки на что-то по id. –

+0

о, извините. Я обновил свой ответ. Надеюсь это ответит на твой вопрос. – fisherwebdev

+0

Я не был достаточно ясен :) Cheers –

 Смежные вопросы

  • Нет связанных вопросов^_^