将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]
答案 0 :(得分:3)
你是对的 - 使用减速器组合,每个减速器都不应该访问该状态的其余部分。问题是为什么您甚至需要商店来包含apollo.item.list[ui.selectedItem]
的单独值。
据推测,您需要此值才能在容器内呈现正确的项目。要计算它,您只需要一个适当的选择器来调用mapStateToProps。通过整个州,获得您需要的价值。一个简化的例子:
const mapStateToProps = state => ({
itemToShow: itemSelector(state)
})
const itemSelector = ({ apollo, ui }) => apollo.item.list[ui.selectedItem]
你需要将你的容器包装在connect
和graphql
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)
我的解决方案是通过compose
将recompose与mapProps
商店和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减速器。看看他们是如何做到的。