简体   繁体   English

如何在Redux中管理(异步)级联数据?

[英]How to manage (async) cascading data in Redux?

Imagine a car configuration app. 想象一下汽车配置应用程序。 Here is an example state tree: 这是一个示例状态树:

{
  // selections
  modelYear,
  modelId,
  transmissionId,

  // options
  modelYears: [],
  models: [],
  transmissions: [],
  accessories: []
}

When the app starts it would load some initial data. 当应用启动时,它将加载一些初始数据。 Then you would start by selecting a model year to populate the list of models, then select a model, then a transmission, accessories, etc. Each piece of data relies on the previous selection in a hierarchical manner. 然后,您将首先选择一个模型年份来填充模型列表,然后选择一个模型,然后选择一个变速器,配件等。每条数据都以分层的方式依赖于先前的选择。 An example sequence of events on page load would be the following: 页面加载事件的示例序列如下:

  1. Retrieve all years and populate a dropdown list. 检索所有年份并填充一个下拉列表。
  2. Select the first year by default 默认选择第一年
  3. Retrieve models based on the selected year 根据所选年份检索模型
  4. Select the first model by default 默认选择第一个模型
  5. Retrieve transmissions based on the selected model 根据所选模型检索传输
  6. Select a transmission by default 默认选择传输
  7. Retrieve accessories based on the selected model etc... 根据所选的型号等检索配件

When the user changes a selection of any piece of the data, new data lower in the hierarchy has to be retrieved and the UI has to be repopulated. 当用户更改对任何数据的选择时,必须检索层次结构中较低的新数据,并且必须重新填充UI。

Here are some snippets of what I have written: 以下是我所写内容的一些摘要:

actions 行动

export function getModelYears() {
  return dispatch => {
    vehiclesApi.getModelYears(years => {
      dispatch(receiveModelYears(years))
    })
  }
}

export function getModels(year) {
  return dispatch => {
    vehiclesApi.getModels(year, models => {
      dispatch(receiveModels(models))
    })
  }
}

function receiveModelYears(years) {
  return {
    type: types.RECEIVE_MODEL_YEARS,
    years: years
  }
}

function receiveModels(models) {
  return {
    type: types.RECEIVE_MODELS,
    models: models
  }
}

export function selectModelYear(year) {
  return {
    type: types.SELECT_MODEL_YEAR,
    year
  }
}

reducers 减速机

function vehicle(state = {}, action) {
  switch (action.type) {
    case SELECT_MODEL_YEAR:
      return Object.assign({}, state, {
        modelYear: action.year
      })
    case SELECT_MODEL:
      return Object.assign({}, state, {
        modelId: action.modelId
      })
    default:
      return state
  }
}  

function modelYears(state = [], action) {
  switch (action.type) {
    case RECEIVE_MODEL_YEARS:
      return state.concat(action.years)
    default:
      return state
  }
}

function models(state = [], action) {
  switch (action.type) {
    case RECEIVE_MODELS:
      return state.concat(action.models)
    default:
      return state
  }
}

I'm not sure how to structure my reducers & actions to handle the default selections and request new data after selections are made. 我不确定如何构造我的化简器和操作来处理默认选择并在选择后请求新数据。 The manual actions are easy (user clicks, dispatch action). 手动操作很容易(用户单击,调度操作)。 But how do I manually dispatch getModels(year) after selecting the first year by default? 但是,如何在默认情况下选择第一年后如何手动调度getModels(year)

Here is the best way I can describe the flow in pseudo code: 这是我用伪代码描述流程的最佳方法:

store.dispatch(getModelYears())

store.subscribe(() => {
  // if model years received
  store.dispatch(selectModelYear(store.getState().modelYears[0]))

  // if modelYear selected
  store.dispatch(getModels(store.getState().modelYear))

  // if models received
  store.dispatch(selectModel(store.getState().models[0].id))

  // if model selected
  store.dispatch(getTransmissions(store.getState().modelId))
  store.dispatch(getAccessories(store.getState().modelId))

  // ...etc
})

I would like to test this system agnostic of any UI framework since I'm building it as a proof of concept for managing my client state and may not be able to use React. 我想测试该系统是否与任何UI框架无关,因为我将其构建为用于管理客户端状态的概念证明,并且可能无法使用React。

If I understood your requirements correctly, you're looking for a way to respond to a state change by triggering another action. 如果我正确理解了您的要求,那么您正在寻找一种通过触发其他操作来响应状态更改的方法。 For example, whenever store.modelYear changes, you need to trigger the RECEIVE_MODELS action. 例如,每当store.modelYear变化,你需要触发RECEIVE_MODELS行动。

The subscribe method looks right for the job. subscription方法适合该工作。 If you want a more structured design, there are patterns built on top of subscribe , for example actors: http://jamesknelson.com/join-the-dark-side-of-the-flux-responding-to-actions-with-actors/ 如果你想要一个更结构化的设计,也有建立在顶部模式subscribe ,例如演员: http://jamesknelson.com/join-the-dark-side-of-the-flux-responding-to-actions-with -actors /

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM