如何在 Redux Reducer 中使用 GraphQL Mutations

How to use GraphQL Mutations inside a Redux Reducer

我这里有一个 React 无状态函数,我想从我的减速器中调用我的突变。请注意,在 React.Component Class 中调用突变是通过在组件中添加一个函数来实现的,我不想这样,我想使用我的 reducer 来做到这一点。

使用最少的代码示例,我将展示我的设置

// index.js render function


[...] // imported variables

<ApolloProvider client={client}>
  <Provider store={store}>
    <ConnectedRouter history={history}>
      <div>
        <App />
      </div>
    </ConnectedRouter>
  </Provider>
</ApolloProvider>

// Mutation
const Foo = gql`
  mutation Foo($id: String) {
    AddBar(id: $id) {
     id
    }
  }
`;

// Component
[...] // other imports for below variables
const Comp = (props) => (
  <div>
    <button onClick={() => props.addFoo(props)}>Click</button>
  </div>
)

const mapDispatchToProps = dispatch => bindActionCreators({
  addFoo
}, dispatch)

export default connect(
 mapDispatchToProps
)(graphql(Foo)(Comp))

// Reducer (very slimmed with just the action)

export const addFoo = (props) => {

 // props contained the mutate function 
 props.mutate({

   variables: {id: "1" }

 })

  // dispatch goes here but not needed.

}

好的,我已经尽可能精简了这个例子。我的问题是我的变量没有传递给我的突变函数。如果我用一个硬编码 id 并单击按钮,graphql 会更改我的数据(是),但唯一的问题是变量没有传递。在检查器中,我确实看到了具有正确值的变量,但是......没有传递给 mutate 函数。

一些想法...

首先,reducer 不应该改变数据或进行异步调用。它们应该是没有副作用的纯函数。

暂时不考虑 GraphQL,假设您只有一个 REST 调用,您通常会在 Action Creator 或类似的东西中发生变化。 Redux 中的 Action Creators 本质上是同步的,因此您可以使用 Redux Thunks or Redux Sagas (或类似的东西)来帮助实现这一点。

好的,让我们把 GraphQL 放回去。正如您所指出的,如果您在组件中包含变更,则很难将其连接到您的 Redux 实现中。这两者有点相互排斥。在您的 Redux 实现中,尽管您通常会进行异步 fetch 调用,但您可以使用没有 React 的 Apollo Client 来 mutate...

const apolloClient = createApolloClient();
apolloClient.mutate({mutation: Foo}).then(handleResult)

现在,createApolloClient() 做什么?您不想每次都创建一个新的。该客户端维护一个缓存,并可以处理所有来自重新使用客户端的增值。这适用于 React 代码。您希望从 React 绑定执行的任何查询都使用您在 Redux 操作创建者中使用的相同客户端。该 createApolloClient() 函数需要创建一个客户端单例并 return 它以便您也可以在 ApolloProvider 中使用它:

<ApolloProvider client={createApolloClient()}>

希望对您有所帮助!