【问题标题】:How to use GraphQL Mutations inside a Redux Reducer如何在 Redux Reducer 中使用 GraphQL Mutations
【发布时间】: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 函数。

【问题讨论】:

    标签: reactjs redux graphql create-react-app


    【解决方案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 中分离出来。
    猜你喜欢
    • 2023-03-22
    • 1970-01-01
    • 2020-08-25
    • 2016-06-21
    • 2020-10-01
    • 2016-05-30
    • 1970-01-01
    • 1970-01-01
    • 2020-04-24
    相关资源
    最近更新 更多