如何在 Redux Reducer 中使用 GraphQL Mutations

Posted

技术标签:

【中文标题】如何在 Redux Reducer 中使用 GraphQL Mutations【英文标题】:How to use GraphQL Mutations inside a Redux Reducer 【发布时间】:2018-04-22 12:40:04 【问题描述】:

我在这里有一个 react 无状态函数,我很想从我的 reducer 中调用我的突变。请注意,在 React.Component 类中调用突变是通过在组件中添加一个函数来实现的,我不希望这样,我想使用我的 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 函数。

【问题讨论】:

【参考方案1】:

一些想法......

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

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

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

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

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

<ApolloProvider client=createApolloClient()>

我希望这会有所帮助!

【讨论】:

你是说我的 reducer 中不应该有那个 mutate 函数,它应该在组件中? 不完全是。我是说你不应该在你的 reducer 中使用 mutate 函数,但没有对它应该去哪里发表意见。 Reducers 不应该有副作用,所以他们不应该进行异步调用或修改任何东西。它们应该是来自输入 => 状态的纯粹转换。之后,您可以决定在哪里进行突变。如果你想在 Redux 级别使用它,我更喜欢通过 Redux Thunks 的“Action Creator”机制。您可以使用apolloClient.mutate() 将其放在那里。如果你想把它保留在 React 层,那也很好,你不需要做太多。 我认为你是对的。我将从 redux 中删除所有逻辑并将 graphql 分开。谢谢。 BTH,你的实现是可行的,但我会把它从 Redux 中分离出来。

以上是关于如何在 Redux Reducer 中使用 GraphQL Mutations的主要内容,如果未能解决你的问题,请参考以下文章