繁体   English   中英

如何同步Redux和Relay?

[英]How to synchronize Redux and Relay?

情况

我有一个入职的场景,用户经历一步一步的入职。 我想用Redux管理用户进度的客户端状态。 服务器和客户端之间的同步已经在Relay中实现,但我仍然需要一个Redux存储来进行客户端状态管理。 因此,同步Relay- / Redux-Store会出现问题。

我现在正在做的是用Redux包装我的React组件,然后用Relay包装:

// OnboardProgressView.js
// ...      

// wrap React component with Redux 
const mapStateToProps = (state) => {
  return {
    onboardProgress: state.onboardProgress,
  }
}

const ReduxContainer = connect(
  mapStateToProps,
)(OnboardProgressView)

// this is only for convenience of access of the Relay data
const MappedOnboardProgressView = mapProps({
  params: (props) => props.params,
  user: (props) => props.viewer.user,
})(ReduxContainer)

// wrap Redux component with Relay
export default Relay.createContainer(MappedGettingStartedView, {
  fragments: {
    viewer: () => Relay.QL`
      fragment on Viewer {
        user {
          userId
          onboardProgressStep
        }
        # more stuff ...
      }
    `,
  },
})  

我的进步

我找到了完成不同操作的方法如下:

使用服务器数据初始化Redux存储

我正在使用异步原始中继查询创建存储后立即初始化Redux状态。 为了实现这一点,我也使用了redux-thunk中间件。 Redux发起对Relay的请求,该请求查询服务器。 视觉表示(箭头表示数据流,元素的顺序反映'调用顺序'): Redux <= Relay <= Server

// app.js
const store = createStore(reducer, applyMiddleware(thunk))
store.dispatch(fetchOnboardProgress())

// onboardProgress.js
export function fetchOnboardProgress () {
  return function (dispatch) {
    var query = Relay.createQuery(Relay.QL`
      query {
        viewer {
          user {
            id
            onboardProgress
          }
        }
      }`, {})

    return new Promise(function (resolve, reject) {
      Relay.Store.primeCache({query}, ({done, error}) => {
        if (done) {
          const data = Relay.Store.readQuery(query)[0]
          dispatch(update(data.user.onboardProgress, data.user.id))
          resolve()
        } else if (error) {
          reject(Error('Error when fetching onboardProgress'))
        }
      })
    })
  }
}

在分派Redux操作时更新服务器上的数据

Redux => Relay => Server

为了获得一致的状态更改,当用户进入新手入门过程时,我会触发一个Redux操作,该操作也将异步执行Relay突变。 我也在为此目的使用redux-thunk

function nextStep () {
  return function (dispatch, getState) {
    const currentStep = getState().onboardProgress.step
    const currentStepIndex = OnboardProgress.steps.indexOf(currentStep)
    const nextStep = OnboardProgress.steps[currentStepIndex + 1]
    const userId = getState().onboardProgress._userId

    return _updateReduxAndRelay(dispatch, nextStep, userId)
  }
}

function _updateReduxAndRelay (dispatch, step, userId) {
  return new Promise((resolve, reject) => {
    Relay.Store.commitUpdate(new UpdateUserMutation({
      userId: userId,
      onboardProgressStep: step,
    }), {
      onSuccess: () => {
        dispatch(update(step, userId))
        resolve()
      },
      onFailure: reject,
    })
  })
}

export function update (step, userId) {
  const payload = {onboardProgress: new OnboardProgress({step, userId})}
  return {type: UPDATE, payload}
}

打开问题

我仍然没有找到解决以下情况的方法:

在中继存储更新时更新Redux存储

对服务器上的数据的更改可能具有外部源,这些源不是由我们的应用程序中的用户操作触发的。 使用Relay,我们可以通过forceFetching或polling来解决这个问题。 中继查询如下所示: Relay <= Server 我想另外拥有这个数据流:当外部数据发生变化时, Relay => Redux

需要使用新数据更新Redux存储的另一个可能原因是我们想要同步深度嵌套在中继存储中的数据,或者是复杂查询的一部分。

例如,想一想博客文章的评论数量。 当用户发布新评论时,显示评论计数的另一个组件也应该更新。

如果我们在Redux中管理这些信息,我们需要一种方法来在Relay查询附带新信息时触发Redux操作。 我不知道这种回调,或其他解决方案。

我的问题

在这方面,我有这些问题:

  1. 我现有的方法可以改进什么? 我做的事情是非常危险/会导致不一致吗? (见我的进步
  2. 如果由于某种原因正在更新中继存储,我如何设置同步Redux存储。 我正在寻找React组件生命周期方法或Relay回调,然后我可以将Redux操作发送到Redux存储。 (参见未解决的问题

RelayNetworkLayer是你应该用来同步redux商店和中继器的,因为它允许你订阅那里发生的一切。 如果还有其他想法,我稍后会更新这篇文章。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM