我应该根据调用的OR来组织我的react redux reducer组合还是基于reducer管理的状态?

时间:2016-08-25 23:38:42

标签: javascript reactjs redux react-redux reducers

我正在学习构建一个pokedex应用程序,在您输入名称并点击提交后,它会为您提供有关宠物小精灵的信息。它必须通过2次通话才能获得正确的信息,第一次获得它的高度和重量,然后第二次得到它的描述(例如“Charmander通常可以在炎热地区找到......”)。以下是我的行动明细。

export const fetchPokemon = function (pokemonName) {
  return function (dispatch) {
    dispatch(requestPokemon(pokemonName))
    const requestURL = `http://pokeapi.co/api/v2/pokemon/${pokemonName}/`
    return $.ajax({
      url: requestURL,
    }).done(function (data) {
      dispatch(receivePokemon(data))
      return fetchPokemonDescription(pokemonName)
    }).done(function (res) {
      dispatch(receivePokemonDescription(res))
    })
  }
}

...

export const fetchPokemonDescription = function (pokemonName) {
  return function (dispatch) {
    dispatch(requestPokemonDescription(pokemonName))
    const requestURL = `http://pokeapi.co/api/v2/pokemon-species/${pokemonName}/`
    return $.ajax({
      url: requestURL,
    })
  }
}

我应该为每次通话分别使用减速机吗?看看有关reducer composition的文档,我不确定它是否会使1个减速器与2个减速器更清晰。 2个调用并不是每个人都相互依赖,但是每个不同的口袋妖怪输入都需要进行两次调用,并且两者都返回的数据属于一个口袋妖怪所以我认为它应该在一个减速器中处理状态的一部分

2 个答案:

答案 0 :(得分:1)

我会在你的情况下使用1个reducer。

看到你的州结构会很有用,但我认为你有类似的东西:

currentPokemon: {
  name: ...
  height: ...
  weight: ...
  description: ...
}

如果是这种情况,我会使用1个reducer,因为你只管理一个状态的分支(currentPokemon)。

减速器将切换动作:在一种情况下,它将更新高度和重量,在另一种情况下描述:

export default function currentPokemonReducer (state = initialState, action) {
  switch(action.type) {
    case DATA_RECEIVED:
      return {
        ...state,
        height: action.payload.height,
        weight: action.payload.weight
      }
    case DESCRIPTION_RECEIVED:
      return {
        ...state,
        description: action.payload
      }

    ...

    default:
      return state;
    }
}

答案 1 :(得分:0)

您正在制作的AJAX通话应与动作类型配对。然后,您应该返回类型和有效负载,我假设您的代码,您打算请求响应。

//as we have it added as cdn in the head, jQuery is available
jQuery = window.jQuery;
$ = window.jQuery;


meteorInstall({
    node_modules: {
        jquery: function (r, e, module) {
            module.exports = jQuery;
        }
    }
});

你的行动可能看起来像这样:

//Now sure where these functional are define or what they do, but I'll assume they are selectors of some sort?
export const fetchPokemon = function (pokemonName) {
  return function (dispatch) {
    dispatch(requestPokemon(pokemonName))
    const requestURL = `http://pokeapi.co/api/v2/pokemon/${pokemonName}/`
    return $.ajax({
      url: requestURL,
    }).done(function (data) {
      dispatch(receivePokemon(data))
      return fetchPokemonDescription(pokemonName)
    }).done(function (res) {
      dispatch(receivePokemonDescription(res))
    })
  }
}

最佳做法是单独定义您的类型,以便将它们拉入您的操作文件和reducer文件。很多构建动作和减速器的方法取决于你的响应对象。

const data = fetchPokemon(Charmander);
//this can be defined somewhere else in your app, should not be in your actions file.    

export const pokemonAction(data) {
  return {
    type: "GET_POKEMON_NAME",
    payload: data.name
  }
}

//repeat for any other call

根据您想要塑造您的状态的方式,可以以多种不同的方式使用减速器。您应该考虑如何在整个应用程序中使用此信息。上面的例子给出了一个属性,让我们称它为“口袋妖怪”,并且该属性值是上述两个属性的对象。

例如,如果您只想提取名称并且不想将其作为export const getPokemonReducer(state= {}, action) { if(action.type === "GET_POKEMON_NAME") { return { ...state, [pokemonName]: action.payload } if(action.type === "GET_POKEMON_DESC") { return { ...state, [pokemonDesc]: action.payload } } 拉入,那么您可能会考虑使用单独的减速器。我还会考虑研究诸如this.props.pokemon.pokemonNameaxios之类的抽象,这使得在redux中更容易管理异步调用。