【问题标题】:Redux - why loading everything in state at rootRedux - 为什么在根目录下加载所有状态
【发布时间】:2016-03-12 05:16:48
【问题描述】:

我正在尝试理解 Redux,但遇到了一些困难。

我理解 combineReducer 的概念,即....

var reducer = combineReducers({
    user: userReducer,
    products: productsReducer
})

但是,如果我有数千种产品,只能在产品页面上找到。我不明白为什么我需要在根目录下加载它们;对我来说,这将减慢应用程序的初始启动速度,因为除非用户转到产品页面,否则不需要这些东西。

这只是 redux 的方式吗?

【问题讨论】:

    标签: reactjs redux redux-framework redux-thunk


    【解决方案1】:

    在 Redux 应用程序中,您总是在开始时构建整个状态。使用 Redux,你有一个 store 和一个 state——一切都应该从一个 state 向下渗透到组件上的 props。但是,这并不意味着您实际上需要在启动时将所有 数据 加载到状态中,只是 结构 需要在那里。这就是为什么你应该为每个 reducer 设置一个初始状态对象。

    假设您从数据库加载了数千条产品记录。在您的产品减速器中,您可以执行以下操作:

    const initialState = {
        data: []
    };
    
    //use ES6 default parameters
    function productsReducer (state = initialState, action) {
        switch (action.type) {
        case 'GET_PRODUCTS':
            //return data from action
            return {
                data: action.result
            };
        default: 
            return state;
        }
    }
    

    这意味着当你启动你的应用程序时,如果你使用你在帖子中声明的完整 reducer,你的应用程序状态将如下所示:

    {
        user: {},
        products: {
            data: []
        }
    }
    

    products.data 将是一个空数组,直到您触发实际需要您加载产品数据的操作(即您转到应用程序中的产品页面或其他内容)。确实,如果您随后转到应用程序中的其他位置,产品数据将保留在您的状态中,但这是一件好事 - 下次您呈现产品页面时,您将已经拥有可供您使用的数据,而无需创建数据库查找。

    【讨论】:

    • 谢谢老兄,我还没有看到它解释得像你刚才那样。你现在展示的对我来说很有意义。我希望有更多关于远程数据的真实世界示例和更少的待办事项:(。但是谢谢!
    • 我应该指出,我在 reducer 中稍微编辑了我的评论,因为从技术上讲,您不应该在 reducer 中进行 ajax 调用(尽管它通常会起作用)。更好的流程是在您的操作中创建您的 ajax 调用(承诺),然后有一些中间件为您运行它并将其发送到减速器。我发现本教程非常有帮助。特别是查看 src 并查看 promise-middleware 以及它是如何实现的github.com/happypoulp/redux-tutorial
    • @SarasotaSun:你看过redux repo 中的“真实世界的例子”吗? github.com/rackt/redux/tree/master/examples/real-world
    【解决方案2】:

    在我们的应用中,我们为产品制作了一个 API,每页限制为 15 个。所以我们的 reducer 是这样的。

    collection: {
      "total": 0,
      "per_page": 0,
      "current_page": 0,
      "last_page": 0,
      "from": 0,
      "to": 0,
      data: []
    },
    
    isFetching: false,
    isFetchingError: false
    

    在第一次加载时,我们获取了有限数量的产品,然后我们对其进行了分页.. 在 redux 中使用选择器https://github.com/rackt/reselect

    加载成千上万的数据会使您的应用变得非常缓慢。

    const paginated = (state = initialState, action) => {
     switch (action.type) {
    case FETCH_PAGINATED_PRODUCTS:
      return {
        ...state,
        isFetching: true,
        isFetchingError: false
      };
    
    case FETCH_PAGINATED_PRODUCTS_SUCCESS:
      return {
        ...state,
        collection: action.payload,
        isFetching: false
      };
    
    case FETCH_PAGINATED_PRODUCTS_ERROR:
      return {
        ...state,
        isFetching: false,
        isFetchingError: true
      };
    
    default:
     return state
    

    我们使用axios 请求: https://github.com/mzabriskie/axios

    【讨论】:

    • 你有一个 github 仓库吗?
    • 它是一个私人仓库,我们在公司使用它。机密事项。只是在这里给你一些想法:)
    • 我明白了。有一个关于你如何使用 redux 在 axios 上处理异步的示例?
    【解决方案3】:

    下面是我们如何在 redux-async 中实现 axios

     export function getAll(page = 1) {
      return (dispatch, getState) => {
        const state = getState();
        const { filters } = state.products.paginated;
    
        if ( state.products.paginated.isFetching ) {
          return;
        }
    
        dispatch({ type: FETCH_PAGINATED_PRODUCTS });
    
        return axios
          .get(`products?page=${page}&limit=16&filters=${JSON.stringify(filters)}`)
          .then((res) => dispatch({
            type: FETCH_PAGINATED_PRODUCTS_SUCCESS,
            payload: res.data
          }))
          .catch((res) => dispatch({
            type: FETCH_PAGINATED_PRODUCTS_ERROR,
            /*payload: res.data.error,*/
            error: true
          }));
      }
    }
    
    export function get(id) {
      return (dispatch, getState) => {
        const state = getState();
    
        if ( state.products.resource.isFetching ) {
          return;
        }
    
        dispatch({ type: FETCH_PRODUCT });
    
        return axios
          .get(`products/${id}`)
          .then((res) => dispatch({
            type: FETCH_PRODUCT_SUCCESS,
            payload: res.data.data
          }))
          .catch((res) => dispatch({
            type: FETCH_PRODUCT_ERROR,
            /*payload: new Error(res.data.error),*/
            error: true
          }));
      }
    

    【讨论】:

      猜你喜欢
      • 2019-08-30
      • 2018-01-08
      • 2019-10-30
      • 2020-01-26
      • 2020-12-07
      • 1970-01-01
      • 1970-01-01
      • 2017-01-25
      相关资源
      最近更新 更多