Redux: Opinions/examples 后端持久化怎么做?
Redux: Opinions/examples of how to do backend persistence?
我想知道使用 Redux 的人们如何处理他们的后端持久性。特别是,您是将 "actions" 存储在数据库中还是仅存储应用程序的最后已知状态?
如果您正在存储操作,您是否只是从服务器请求它们,然后在给定页面加载时重播所有这些操作?这不会导致有很多操作的大型应用程序出现性能问题吗?
如果您只存储 "current state",当客户端发生操作时,您实际上如何在任何给定时间保持此状态?
有人有关于如何将 redux reducer 连接到后端存储 api 的一些代码示例吗?
我知道这是一个非常 "it depends on your app" 类型的问题,但我只是在这里思考一些想法,并试图了解这种 "stateless" 架构如何在一个完整的环境中工作-堆栈意义。
谢谢大家
绝对持久化你的减速器的状态!
如果您坚持执行一系列操作,那么您将永远无法在前端修改您的操作,除非在您的 prod 数据库中摆弄。
示例:将一个 reducer 的状态持久化到服务器
我们将从三种额外的操作类型开始:
// actions: 'SAVE', 'SAVE_SUCCESS', 'SAVE_ERROR'
我使用 redux-thunk 进行异步服务器调用:这意味着一个动作创建者函数可以 dispatch
额外的动作并检查当前状态。
save
动作创建者会立即调度一个动作(这样您就可以显示微调器,或禁用 [=49=] 中的 'save' 按钮)。一旦 POST 请求完成,它就会调度 SAVE_SUCCESS
或 SAVE_ERROR
操作。
var actionCreators = {
save: () => {
return (dispatch, getState) => {
var currentState = getState();
var interestingBits = extractInterestingBitsFromState(currentState);
dispatch({type: 'SAVE'});
window.fetch(someUrl, {
method: 'POST',
body: JSON.stringify(interestingBits)
})
.then(checkStatus) // from https://github.com/github/fetch#handling-http-error-statuses
.then((response) => response.json())
.then((json) => dispatch actionCreators.saveSuccess(json.someResponseValue))
.catch((error) =>
console.error(error)
dispatch actionCreators.saveError(error)
);
}
},
saveSuccess: (someResponseValue) => return {type: 'SAVE_SUCCESS', someResponseValue},
saveError: (error) => return {type: 'SAVE_ERROR', error},
// other real actions here
};
(N.B。$.ajax
完全可以代替 window.fetch
的东西,我只是不想为一个函数加载整个 jQuery!)
reducer 只跟踪任何未完成的服务器请求。
function reducer(state, action) {
switch (action.type) {
case 'SAVE':
return Object.assign {}, state, {savePending: true, saveSucceeded: null, saveError: null}
break;
case 'SAVE_SUCCESS':
return Object.assign {}, state, {savePending: false, saveSucceeded: true, saveError: false}
break;
case 'SAVE_ERROR':
return Object.assign {}, state, {savePending: false, saveSucceeded: false, saveError: true}
break;
// real actions handled here
}
}
您可能想要对从服务器返回的 someResponseValue
做一些事情 - 也许它是一个新创建的实体的 ID 等等。
我希望这对您有所帮助,到目前为止它对我来说效果很好!
坚决坚持!
这只是一个反例,添加到上一个答案中 Dan Fitch 的 。
如果你坚持你的状态,你将永远无法在不改变数据库中的列和表的情况下修改你的状态。状态只显示现在的情况,你无法重建以前的状态,你也不知道发生了什么事实。
示例:将操作持久化到服务器
您的 action
已经是 "type" 和 "payload",这可能是您在 Event-Driven/Event-Sourcing 架构中所需要的全部。
您可以调用 back-end 并在 actionCreator
中发送操作(参见 Dan Fox 的 )。
另一种选择 是使用 middleware 来过滤您需要保留的操作,并将它们发送到您的后端,并且可以选择将新事件发送到你的商店。
const persistenceActionTypes = ['CREATE_ORDER', 'UPDATE_PROFILE'];
// notPersistenceActionTypes = ['ADD_ITEM_TO_CART', 'REMOVE_ITEM_FROM_CART', 'NAVIGATE']
const persistenceMiddleware = store => dispatch => action => {
const result = dispatch(action);
if (persistenceActionTypes.indexOf(action.type) > -1) {
// or maybe you could filter by the payload. Ex:
// if (action.timestamp) {
sendToBackend(store, action);
}
return result;
}
const sendToBackend = (store, action) => {
const interestingBits = extractInterestingBitsFromAction(action);
// déjà vu
window.fetch(someUrl, {
method: 'POST',
body: JSON.stringify(interestingBits)
})
.then(checkStatus)
.then(response => response.json())
.then(json => {
store.dispatch(actionCreators.saveSuccess(json.someResponseValue));
})
.catch(error => {
console.error(error)
store.dispatch(actionCreators.saveError(error))
});
}
import { createStore, applyMiddleware } from 'redux'
import thunk from 'redux-thunk';
createStore(
yourReducer,
aPreloadedState,
applyMiddleware(thunk, persistenceMiddleware)
)
(您也可以使用中间件将当前状态发送到后端。调用 store.getState()
。)
您的应用已经知道如何使用 reducers
将操作转换为状态,因此您也可以从后端获取操作。
我想知道使用 Redux 的人们如何处理他们的后端持久性。特别是,您是将 "actions" 存储在数据库中还是仅存储应用程序的最后已知状态?
如果您正在存储操作,您是否只是从服务器请求它们,然后在给定页面加载时重播所有这些操作?这不会导致有很多操作的大型应用程序出现性能问题吗?
如果您只存储 "current state",当客户端发生操作时,您实际上如何在任何给定时间保持此状态?
有人有关于如何将 redux reducer 连接到后端存储 api 的一些代码示例吗?
我知道这是一个非常 "it depends on your app" 类型的问题,但我只是在这里思考一些想法,并试图了解这种 "stateless" 架构如何在一个完整的环境中工作-堆栈意义。
谢谢大家
绝对持久化你的减速器的状态!
如果您坚持执行一系列操作,那么您将永远无法在前端修改您的操作,除非在您的 prod 数据库中摆弄。
示例:将一个 reducer 的状态持久化到服务器
我们将从三种额外的操作类型开始:
// actions: 'SAVE', 'SAVE_SUCCESS', 'SAVE_ERROR'
我使用 redux-thunk 进行异步服务器调用:这意味着一个动作创建者函数可以 dispatch
额外的动作并检查当前状态。
save
动作创建者会立即调度一个动作(这样您就可以显示微调器,或禁用 [=49=] 中的 'save' 按钮)。一旦 POST 请求完成,它就会调度 SAVE_SUCCESS
或 SAVE_ERROR
操作。
var actionCreators = {
save: () => {
return (dispatch, getState) => {
var currentState = getState();
var interestingBits = extractInterestingBitsFromState(currentState);
dispatch({type: 'SAVE'});
window.fetch(someUrl, {
method: 'POST',
body: JSON.stringify(interestingBits)
})
.then(checkStatus) // from https://github.com/github/fetch#handling-http-error-statuses
.then((response) => response.json())
.then((json) => dispatch actionCreators.saveSuccess(json.someResponseValue))
.catch((error) =>
console.error(error)
dispatch actionCreators.saveError(error)
);
}
},
saveSuccess: (someResponseValue) => return {type: 'SAVE_SUCCESS', someResponseValue},
saveError: (error) => return {type: 'SAVE_ERROR', error},
// other real actions here
};
(N.B。$.ajax
完全可以代替 window.fetch
的东西,我只是不想为一个函数加载整个 jQuery!)
reducer 只跟踪任何未完成的服务器请求。
function reducer(state, action) {
switch (action.type) {
case 'SAVE':
return Object.assign {}, state, {savePending: true, saveSucceeded: null, saveError: null}
break;
case 'SAVE_SUCCESS':
return Object.assign {}, state, {savePending: false, saveSucceeded: true, saveError: false}
break;
case 'SAVE_ERROR':
return Object.assign {}, state, {savePending: false, saveSucceeded: false, saveError: true}
break;
// real actions handled here
}
}
您可能想要对从服务器返回的 someResponseValue
做一些事情 - 也许它是一个新创建的实体的 ID 等等。
我希望这对您有所帮助,到目前为止它对我来说效果很好!
坚决坚持!
这只是一个反例,添加到上一个答案中 Dan Fitch 的
如果你坚持你的状态,你将永远无法在不改变数据库中的列和表的情况下修改你的状态。状态只显示现在的情况,你无法重建以前的状态,你也不知道发生了什么事实。
示例:将操作持久化到服务器
您的 action
已经是 "type" 和 "payload",这可能是您在 Event-Driven/Event-Sourcing 架构中所需要的全部。
您可以调用 back-end 并在 actionCreator
中发送操作(参见 Dan Fox 的
另一种选择 是使用 middleware 来过滤您需要保留的操作,并将它们发送到您的后端,并且可以选择将新事件发送到你的商店。
const persistenceActionTypes = ['CREATE_ORDER', 'UPDATE_PROFILE'];
// notPersistenceActionTypes = ['ADD_ITEM_TO_CART', 'REMOVE_ITEM_FROM_CART', 'NAVIGATE']
const persistenceMiddleware = store => dispatch => action => {
const result = dispatch(action);
if (persistenceActionTypes.indexOf(action.type) > -1) {
// or maybe you could filter by the payload. Ex:
// if (action.timestamp) {
sendToBackend(store, action);
}
return result;
}
const sendToBackend = (store, action) => {
const interestingBits = extractInterestingBitsFromAction(action);
// déjà vu
window.fetch(someUrl, {
method: 'POST',
body: JSON.stringify(interestingBits)
})
.then(checkStatus)
.then(response => response.json())
.then(json => {
store.dispatch(actionCreators.saveSuccess(json.someResponseValue));
})
.catch(error => {
console.error(error)
store.dispatch(actionCreators.saveError(error))
});
}
import { createStore, applyMiddleware } from 'redux'
import thunk from 'redux-thunk';
createStore(
yourReducer,
aPreloadedState,
applyMiddleware(thunk, persistenceMiddleware)
)
(您也可以使用中间件将当前状态发送到后端。调用 store.getState()
。)
您的应用已经知道如何使用 reducers
将操作转换为状态,因此您也可以从后端获取操作。