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

时间:2017-07-07 16:14:52

标签: node.js reactjs react-redux graphql react-apollo

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

{
    apollo: // results from Apollo queries
}

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

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

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

使用reducer composition,我们ui州的缩减者将无法访问阿波罗州的任何内容。

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

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

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

apollo.item.list[ui.selectedItem]

3 个答案:

答案 0 :(得分:3)

你是对的 - 使用减速器组合,每个减速器都不应该访问该状态的其余部分。问题是为什么您甚至需要商店来包含apollo.item.list[ui.selectedItem]的单独值。

据推测,您需要此值才能在容器内呈现正确的项目。要计算它,您只需要一个适当的选择器来调用mapStateToProps。通过整个州,获得您需要的价值。一个简化的例子:

const mapStateToProps = state => ({
  itemToShow: itemSelector(state)
})

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

你需要将你的容器包装在connectgraphql HOC中才能完成这项工作,尽管据我所知,你是否将它包装在一个或另一个中好像很重要。您还可以考虑使用reselect,这对于这样的派生数据是理想的。

编辑:由于Apollo的商店大块并没有真正设计为如上所述,你可能会发现更容易将其分解为两个步骤:首先,分配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来获得更清洁的方法。

答案 1 :(得分:2)

我的解决方案是通过composerecomposemapProps商店和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让我指向正确的方向。

答案 2 :(得分:0)

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