我应该基于调用来组织我的react redux reducer组合还是基于一个reducer管理的状态

Should I organize my react redux reducer composition based on the calls made OR based on the state a reducer manages?

本文关键字:reducer 组合 redux 于一个 状态 管理 react 我的 于调用 调用 我应该      更新时间:2023-09-26

我正在学习构建一个pokedex应用程序,在您输入名称并点击提交后,可以提供有关pokemon的信息。它必须经过两次调用才能获得正确的信息,第一次获得它的高度和重量,然后第二次获得它的描述(例如。"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为每个调用?看看关于减速器组成的文件,我不确定是否有1个减速器vs 2个减速器会更干净。这两个调用并不依赖于彼此,但是每个不同的口袋妖怪输入都需要进行调用,并且从两个口袋妖怪返回的数据属于一个口袋妖怪,所以我认为它应该在一个减速机中处理状态的一部分。

在你的情况下我会使用1个减速器。

看看你的状态结构会很有用,但我认为你有这样的:

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

如果是这种情况,我会使用1个reducer,因为你只管理状态的1个分支(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;
    }
}

您正在进行的AJAX调用应该与操作类型配对。然后您应该返回类型和有效负载,我假设基于您的代码,您打算请求响应。

//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))
    })
  }
}

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

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

最佳实践是让你的类型单独定义,这样它们就可以被拉到你的actions文件和reducer文件中。在很大程度上,如何构建action和reducer将取决于响应对象。

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
    }
}

reducer可以以许多不同的方式使用,这取决于你想如何塑造你的状态。您应该考虑如何在整个应用程序中使用这些信息。上面的例子给出了一个属性,我们称之为"Pokemon",这个属性值是上述两个属性的一个对象。

例如,如果你只想拉入名称,而不想拉入this.props.pokemon.pokemonName,那么你可能会考虑有一个单独的减速器。我还会考虑考虑axiosredux-promise之类的抽象,它们使异步调用在redux中更容易管理。