Redux - 为什么在根目录下加载所有状态
Redux - why loading everything in state at root
我正在尝试理解 Redux,但遇到了一些困难。
我了解combineReducer的概念,即....
var reducer = combineReducers({
user: userReducer,
products: productsReducer
})
但是,如果我有数千种产品,而且只能在产品页面上找到怎么办?我不明白为什么我需要在根目录下加载它们;对我来说,这会减慢应用程序的初始启动速度,因为除非用户转到产品页面,否则不需要的东西。
redux 就是这样吗?
在 Redux 应用程序中,您总是在一开始就构建整个状态。使用 Redux 你有一个商店和一个状态 - 一切都应该从那个状态滴落到你的组件上的道具。但是,这并不意味着您实际上需要将所有 data 加载到启动时的状态,只是 structure 需要存在。这就是为什么你应该为每个减速器设置一个初始状态对象。
假设您有数千条从数据库中加载的产品记录。在您的产品减速器中,您可以这样做:
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;
}
}
这意味着当您启动您的应用程序时,如果您使用您在 post 中声明的完整减速器,您的应用程序状态将如下所示:
{
user: {},
products: {
data: []
}
}
products.data
将是一个空数组,直到您触发实际需要您加载产品数据的操作(即您转到应用程序中的产品页面或其他内容)。确实,如果您随后转到应用程序的其他位置,产品数据将保留在您的状态中,但这是一件好事 - 下次呈现产品页面时,您将已经拥有数据供您使用,而无需创建数据库查找。
在我们的应用程序中,我们为产品制作了一个 API,每页限制为 15 个。所以我们的减速器是这样的。
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
下面是我们如何在 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,但遇到了一些困难。
我了解combineReducer的概念,即....
var reducer = combineReducers({
user: userReducer,
products: productsReducer
})
但是,如果我有数千种产品,而且只能在产品页面上找到怎么办?我不明白为什么我需要在根目录下加载它们;对我来说,这会减慢应用程序的初始启动速度,因为除非用户转到产品页面,否则不需要的东西。
redux 就是这样吗?
在 Redux 应用程序中,您总是在一开始就构建整个状态。使用 Redux 你有一个商店和一个状态 - 一切都应该从那个状态滴落到你的组件上的道具。但是,这并不意味着您实际上需要将所有 data 加载到启动时的状态,只是 structure 需要存在。这就是为什么你应该为每个减速器设置一个初始状态对象。
假设您有数千条从数据库中加载的产品记录。在您的产品减速器中,您可以这样做:
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;
}
}
这意味着当您启动您的应用程序时,如果您使用您在 post 中声明的完整减速器,您的应用程序状态将如下所示:
{
user: {},
products: {
data: []
}
}
products.data
将是一个空数组,直到您触发实际需要您加载产品数据的操作(即您转到应用程序中的产品页面或其他内容)。确实,如果您随后转到应用程序的其他位置,产品数据将保留在您的状态中,但这是一件好事 - 下次呈现产品页面时,您将已经拥有数据供您使用,而无需创建数据库查找。
在我们的应用程序中,我们为产品制作了一个 API,每页限制为 15 个。所以我们的减速器是这样的。
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
下面是我们如何在 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
}));
}