首页 文章

React Apollo和Redux:将自定义减速器与Apollo状态相结合

提问于
浏览
0

react-apollo 与redux一起使用时,服务器中的数据将缓存在redux存储中的 apollo 键下:

{
    apollo: // results from Apollo queries
}

创建自己的Reducer和相应的状态树后,您的商店可能如下所示:

{
    apollo: { ... },
    ui: {
        selectedItem: 2;
        showItems: 6
    }
}

想象一下,有一个动作可以改变 ui.selectedItem 的值,并且该值是隐藏在 apollo 对象中某个项目的索引 .

使用reducer composition,我们的 ui 州的减速器将无法访问Apollo状态下的任何内容 .

在我们的组件中,我们可以通过 mapStateToProps 订阅 ui 状态的更改,我们可以使用 react-apollo GraphQL容器(或 @graphql 装饰器)将Apollo结果映射到道具 .

但是,我们如何使用Apollo结果和我们应用程序中的其他状态计算出的值来更新我们的商店?

例如,如果 apollo.item.list 是项目数组,并且 ui.selectedItem 是您要在该列表中定位的索引 - 商店如何包含以下值:

apollo.item.list[ui.selectedItem]

3 回答

  • 2

    你是对的 - 使用减速器组合,每个减速器都不应该有进入该状态的其余部分 . 问题是为什么你甚至需要 storeapollo.item.list[ui.selectedItem] 包含一个单独的值 .

    大概你需要这个值来渲染容器中的正确项目 . 要计算它,您只需要一个适当的选择器来调用mapStateToProps . 通过整个州,获得您需要的 Value . 一个简化的例子:

    const mapStateToProps = state => ({
      itemToShow: itemSelector(state)
    })
    
    const itemSelector = ({ apollo, ui }) => apollo.item.list[ui.selectedItem]
    

    您需要将容器包装在 connectgraphql HOC中才能使其正常工作,尽管据我所知,无论您将其包装在一个或另一个中,这似乎并不重要 . 你也可以考虑使用reselect,这是这样的派生数据的理想选择 .

    Edit: 由于Apollo 's chunk of the store wasn' t确实设计为如上所述使用,您可能会发现更容易将其分解为两个步骤:首先,将ui.selectedItem指定给mapStateToProps中的prop . 然后,如果用graphql HOC包装容器,可以像这样引用该prop:

    const mapStateToProps = state => ({ selectedItem });
    const mapDataToProps = ({ ownProps: { selectedItem }, data }) => ({
      itemToShow: data.item.list[selectedItem]
    });
    const ContainerWithData = graphql(myQuery, { props: mapDataToProps })(MyContainer);
    
    export default connect(mapStateToProps)(ContainerWithData);
    

    或者你可以使用apollo-react的 compose 来获得更清洁的方法 .

  • 3

    我的解决方案是通过 mapPropsrecomposecompose 商店和Apollo州一起使用:

    import { mapProps, compose } from ‘recompose’;
    
    const mapStateToProps = state => ({
      selectedItem: state.ui.selectedItem
    })
    
    const mapDataToProps = {
      props: ({ data }) => ({ list: data.item.list })
    }
    
    const selectProps = mapProps(({ selectedItem, list}) => ({
      item: list[selectedItem] 
    }))
    
    export default compose(
      connect(mapStateToProps, {}),
      graphql(MY_QUERY, mapDataToProps),
      selectProps
    )(MyComponent);
    

    这也允许我们使用branch检查 graphql 加载状态,因此在数据可用之前我们不运行 selectProps .

    感谢Daniel Rearden's answer指出我正确的方向 .

  • 0

    对你的问题不是一个真正的答案,但我发现ReactQL是一个很好的入门套件,可以为你处理所有这些事情 . 它拥有Apollo React Redux的所有样板,包括自定义Redux减速器 . 看看他们是如何做到的 .

相关问题