Redux - 为啥在根目录下加载所有状态
Posted
技术标签:
【中文标题】Redux - 为啥在根目录下加载所有状态【英文标题】:Redux - why loading everything in state at rootRedux - 为什么在根目录下加载所有状态 【发布时间】:2016-03-12 05:16:48 【问题描述】:我正在尝试理解 Redux,但遇到了一些困难。
我理解 combineReducer 的概念,即....
var reducer = combineReducers(
user: userReducer,
products: productsReducer
)
但是,如果我有数千种产品,只能在产品页面上找到。我不明白为什么我需要在根目录下加载它们;对我来说,这将减慢应用程序的初始启动速度,因为除非用户转到产品页面,否则不需要这些东西。
这只是 redux 的方式吗?
【问题讨论】:
【参考方案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 github.com/rackt/redux/tree/master/examples/real-world 我明白了。有一个关于你如何使用 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
));
【讨论】:
以上是关于Redux - 为啥在根目录下加载所有状态的主要内容,如果未能解决你的问题,请参考以下文章
我的 Redux 状态发生了变化,为啥 React 没有触发重新渲染?
为啥这个 Redux Saga Selector 不工作?我似乎无法访问状态