在React-Redux中转换API数据:Action或Reducer

roc*_*ock 3 reducers reactjs redux react-redux

我有一个天气应用程序,api数据有不同的格式,所以我编写了一个方法的对象,我可以将数据转换为英制格式和从UTC到GMT的时间.

现在我在reducer中的数据上调用了这些方法.

问题:在将有效负载交付给减速器之前,是否"好"或是否应在相应的操作中完成转换?只是好奇这样的事情的最佳实践是什么.

FYI:我用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
  };
};
Run Code Online (Sandbox Code Playgroud)

减速器:

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;
  }
};
Run Code Online (Sandbox Code Playgroud)

bio*_*tal 8

您有三个位置可以有效地处理原始数据:

  • 组件的render()功能

    这通常不是一个好主意,因为它意味着每次呈现组件时都会处理数据.如果您使用像重新选择这样的包,则可以通过缓存来缓解性能问题,但即使这样,实际的代码(例如 排序过滤)也应保留在mapStateToProps().

  • 在减速机中

    可以对减速器中的处理数据做出更好的处理,但我认为,出于清晰和分离关注的原因,这仍然不是最好的地方.减速器的工作非常明确 - 承认动作并将之前的状态与动作结果合并,只有其他任何东西都可以模糊责任和可测试性.

  • 一个动作thunk

    在我看来,动作thunk是一次性数据转换的正确位置,例如导入的原始数据的规范化/转换.它不仅通常是一个明确的动作子任务(例如,获取天气数据 - >将摄氏温度转换为华氏温度),而且还具有不存储无用数据的附加优势,即使暂时处于状态.

    引用丹阿布拉莫夫的话:

    ...动作对象是发生的事件的最小表示,状态对象是现在渲染所需内容的最小表示.

最后的注释 - 选择器

虽然我在上面说过组件不是执行原始数据转换的好地方,但实际上我认为有一个参数可以用于将原始数据存储在redux-state中并使用像reselect这样的包来呈现规范化或根据selectors需要计算值.

实现此目的的一种方法是具有selector在原始数据的已定义部分上执行数据规范化的功能.使用重新选择包,此转换将被缓存,因此只执行一次.它将具有仅在需要时延迟转换数据的优点.