Redux:如何进行后端持久化的意见/示例?

IT技术 reactjs reactjs-flux redux redux-framework
2021-05-22 07:00:07

我想知道使用 Redux 的人是如何实现后端持久性的。特别是,您是将“操作”存储在数据库中还是仅存储应用程序的最后一个已知状态?

如果您要存储操作,是否只是从服务器请求它们,然后在给定页面加载时重放所有这些操作?对于有很多操作的大型应用程序,这难道不会导致一些性能问题吗?

如果您只存储“当前状态”,那么当客户端上发生操作时,您实际上如何在任何给定时间保持此状态?

有没有人有一些关于如何将 redux reducer 连接到后端存储 api 的代码示例?

我知道这是一个非常“这取决于你的应用程序”类型的问题,但我只是在这里思考一些想法并试图了解这种“无状态”架构如何在全栈意义上工作。

感谢大家。

2个回答

绝对坚持你的减速机的状态!

如果您改为持久化一系列操作,您将永远无法在前端修改您的操作,而无需在 prod 数据库中摆弄。

示例:将一个 reducer 的状态持久化到服务器

我们将从三种额外的操作类型开始:

// actions: 'SAVE', 'SAVE_SUCCESS', 'SAVE_ERROR'

我使用redux-thunk进行异步服务器调用:这意味着一个动作创建器函数可以dispatch额外动作并检查当前状态。

save行动的创建者立即派遣一个动作(这样就可以显示在你的UI中的微调,或禁用“保存”按钮)。一旦 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
};

(NB$.ajax完全可以代替这些window.fetch东西,我只是不想为一个函数加载整个 jQuery!)

减速器只跟踪任何未完成的服务器请求。

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已经是一个“类型”和一个“有效载荷”,这可能就是你在事件驱动/事件源架构中所需要的。

您可以调用您的后端并在您的内部发送操作actionCreator(请参阅 Dan Fox 的回答)。

另一种替代方法是使用中间件来过滤您需要保留哪些操作,并将它们发送到您的后端,并且可以选择将新事件分派到您的商店。

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,因此您也可以从后端获取操作。