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