我有一个天气应用程序,api数据有不同的格式,所以我编写了一个方法对象,我可以将数据转换为英制格式和时间从UTC到GMT。
现在我在reducer中的数据上调用了这些方法。
问题:那是"好吗"或者应该在有效载荷交付给减速器之前在相应的动作中进行转换?只是好奇这样的事情的最佳实践是什么。
仅供参考:我使用axios
作为基于承诺的HTTP客户端redux-promise-middleware
,redux-lodger
,& redux-promise
作为商店中的中间件。
行动创作者:
export const fetchCurrentWeather = (city) => {
const url = `${CURRENT_ROOT_URL}&q=${city},us`;
const promise = new Promise((resolve, reject) => {
axios.get(url)
.then(res => resolve(res.data))
.catch(err => reject(err));
});
return {
type: FETCH_CURRENT_WEATHER,
payload: promise
};
};
减速机:
export default(state = initialState, action) => {
const data = action.payload;
switch (action.type) {
case `${FETCH_CURRENT_WEATHER}_PENDING`:
return {};
case `${FETCH_CURRENT_WEATHER}_FULFILLED`:
const prefix = 'wi wi-owm-';
const code = data.weather[0].id;
const icon = prefix + code;
return {
...state,
weatherData: {
humidity: data.main.humidity,
icon,
name: data.name,
pressure: unitConverter.toInchesHG(data.main.pressure),
sunrise: unitConverter.toGMT(data.sys.sunrise),
sunset: unitConverter.toGMT(data.sys.sunset),
temp: unitConverter.toFarenheit(data.main.temp),
winddir: unitConverter.toCardinal(data.wind.deg),
windspd: unitConverter.toMPH(data.wind.speed)
},
isFetched: true
};
case `${FETCH_CURRENT_WEATHER}_REJECTED`:
return {
...state,
isFetched: true,
err: data
};
default:
return state;
}
};
答案 0 :(得分:8)
您有三个位置可以有效地处理原始数据:
组件的render()
功能
这通常不是一个好主意,因为它意味着每次呈现组件时都会处理数据。如果您使用像reselect这样的程序包,则可以通过缓存来缓解性能问题,但即使这样,实际代码也可以排序或过滤应保存在mapStateToProps()
。
在缩减器中
可以对减速器中的处理数据做出更好的处理,但我认为,出于清晰和分离关注的原因,这仍然不是最佳选择。减速器的工作非常明确 - 承认动作并将之前的状态与动作结果合并,只有其他任何东西都会模糊责任和可测试性。
行动thunk
在我看来,动作thunk是一次性数据转换的正确位置,例如导入的原始数据的规范化/转换。它不仅通常是一个明确的动作子任务(例如,获取天气数据 - >将摄氏温度转换为华氏温度),而且还具有不存储无用数据的附加优势,即使暂时处于状态。
引用丹·阿布拉莫夫的话:
...动作对象[是]发生的事情的最小表示 状态对象[是]对所需内容的最小表示 现在渲染。
最终注释 - 选择器
虽然我上面说过组件不是执行原始数据转换的好地方,但事实上我认为有一个参数可以将原始数据存储在redux-state中并使用像reselect这样的包来根据需要通过selectors
显示规范化或计算值。
实现此目的的一种方法是使用selector
函数对原始数据的已定义部分执行数据规范化。使用reselect包,此转换将被缓存,因此只执行一次。它只会根据需要延迟转换数据。