我应该根据调用还是根据 reducer 管理的状态来组织我的 react redux reducer 组合?
Should I organize my react redux reducer composition based on the calls made OR based on the state a reducer manages?
我正在学习构建一个 pokedex 应用程序,在您输入名称并点击提交后,它会为您提供有关 pokemon 的信息。它必须经过 2 次调用才能获得正确的信息,第 1 次获得其身高和体重,然后第 2 次获得其描述(例如 "Charmander can usually be found in hot areas...")。以下是我的动作分解。
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 吗?查看有关 reducer composition 的文档,我不确定拥有 1 个减速器与 2 个减速器是否会更清洁。这 2 个调用并不相互依赖,但是每个不同的 pokemon 输入都需要进行两个调用,并且从两者返回的数据属于一个 pokemon 所以我认为它应该在一个 reducer 中处理状态的一部分.
您正在进行的 AJAX 调用应与操作类型配对。然后你应该 return 类型和你的有效负载,我根据你的代码假设你打算请求响应。
//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
最佳做法是单独定义您的类型,以便将它们拉入您的操作文件和缩减程序文件中。很多构建动作和缩减器的方式将取决于您的响应对象。
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
引入,那么您可能会考虑使用一个单独的减速器。我还会考虑研究诸如 axios
和 redux-promise
之类的抽象,它们使异步调用在 redux 中更容易管理。
我会在你的情况下使用 1 个减速器。
看到你的状态结构会很有用,但我认为你有类似的东西:
currentPokemon: {
name: ...
height: ...
weight: ...
description: ...
}
如果是这种情况,我会使用 1 个减速器,因为你只管理状态的 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;
}
}
我正在学习构建一个 pokedex 应用程序,在您输入名称并点击提交后,它会为您提供有关 pokemon 的信息。它必须经过 2 次调用才能获得正确的信息,第 1 次获得其身高和体重,然后第 2 次获得其描述(例如 "Charmander can usually be found in hot areas...")。以下是我的动作分解。
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 吗?查看有关 reducer composition 的文档,我不确定拥有 1 个减速器与 2 个减速器是否会更清洁。这 2 个调用并不相互依赖,但是每个不同的 pokemon 输入都需要进行两个调用,并且从两者返回的数据属于一个 pokemon 所以我认为它应该在一个 reducer 中处理状态的一部分.
您正在进行的 AJAX 调用应与操作类型配对。然后你应该 return 类型和你的有效负载,我根据你的代码假设你打算请求响应。
//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
最佳做法是单独定义您的类型,以便将它们拉入您的操作文件和缩减程序文件中。很多构建动作和缩减器的方式将取决于您的响应对象。
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
引入,那么您可能会考虑使用一个单独的减速器。我还会考虑研究诸如 axios
和 redux-promise
之类的抽象,它们使异步调用在 redux 中更容易管理。
我会在你的情况下使用 1 个减速器。
看到你的状态结构会很有用,但我认为你有类似的东西:
currentPokemon: {
name: ...
height: ...
weight: ...
description: ...
}
如果是这种情况,我会使用 1 个减速器,因为你只管理状态的 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;
}
}