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

时间:2016-11-04 03:35:00

标签: reactjs redux react-redux reducers

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

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

问题:那是"好吗"或者应该在有效载荷交付给减速器之前在相应的动作中进行转换?只是好奇这样的事情的最佳实践是什么。

仅供参考:我使用axios作为基于承诺的HTTP客户端redux-promise-middlewareredux-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;
  }
};

1 个答案:

答案 0 :(得分:8)

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

  • 组件的render()功能

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

  • 在缩减器中

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

  • 行动thunk

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

    引用丹·阿布拉莫夫的话:

      

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

最终注释 - 选择器

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

实现此目的的一种方法是使用selector函数对原始数据的已定义部分执行数据规范化。使用reselect包,此转换将被缓存,因此只执行一次。它只会根据需要延迟转换数据。