如何在 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的主要内容,如果未能解决你的问题,请参考以下文章

如何在 TypeScript 中键入 Redux 操作和 Redux reducer?

如何使用 redux-toolkit 中的 createSlice 方法在不同的 reducer 函数中使用单个动作类型

如何在reducer中专门使用redux来获取react-native中的API?

我如何在 react redux 中访问另一个 reducer 的状态。 reducer 和 store 之间的状态流

使用 Redux 如何阻止 reducer 中的 switch 增长?

如何使用 redux 工具包动态生成 reducer 和 action 类型?