2017-07-07 82 views
0

当使用react-apollo与终极版,服务器上的数据在终极版商店下apollo键缓存:阵营阿波罗和终极版:将自定义减速与阿波罗状态

{ 
    apollo: // results from Apollo queries 
} 

创建自己的减速和相应的状态后,树,你的店可能是这样的:

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

试想一下,有哪些改变的ui.selectedItem价值的作用,而这种价值的项目在apollo某处埋藏指数对象。

随着reducer composition,我们的ui州的减速器将正确无法访问阿波罗州下的任何东西。

在我们的组件,我们可以通过mapStateToProps订阅我们ui状态变化,并且我们可以使用react-apollo GraphQL容器(或@graphql装饰)阿波罗结果映射到道具。

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

例如,如果apollo.item.list是项目的数组,ui.selectedItem是要在该列表中的目标指数 - 如何可以在商店包含一个值:

apollo.item.list[ui.selectedItem] 

回答

2

我的解决办法是使用recomposecompose商店和阿波罗通过mapProps状态一起:

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); 

这也让我们检查使用branchgraphql负荷状态,所以我们不跑selectProps,直到数据可用。

感谢Daniel Rearden's answer指引我在正确的方向。

3

你是对的 - 由减速器组成,每个减速器不应该有权访问其余的州。问题是为什么你甚至需要你的商店包含apollo.item.list[ui.selectedItem]单独的值。

大概你需要这个值来渲染你的容器中正确的东西。为了计算它,你只需要一个合适的选择器在mapStateToProps内调用。通过整个状态,获得你需要的价值。一个简单的例子:

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

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

你需要来包装容器中都connectgraphql肝卵圆细胞,使这项工作,但据我所知,无论你把它包在一个或另一个没有按第一这似乎不重要。您还可以使用reselect进行研究,这对于此类派生数据非常理想。由于Apollo的商店大部分并不是真正用于如上所述的设计,因此您可能会发现将此分解为两个步骤更容易:首先,将ui.selectedItem分配给prop mapStateToProps。然后,如果你与graphql HOC包装容器时,您可以参考该道具,像这样:

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); 

或者你可以使用阿波罗反应的compose更清洁的方式。

+1

谢谢,这是有用的输入。我喜欢第一个解决方案,因为memoization选项和可重复使用的选择器(我可能需要这个在多个容器中 - 因此希望将它存储在第一位)。但正如你所说,这不是真正的使用阿波罗的可靠方法。第二种选择似乎将大量工作放到了'graphql'专题讨论区,似乎不能跨容器重用? – duncanhall

+0

此外,第二个选项似乎只在数据更改时才起作用。如果之后selectedItem状态发生改变,那么'itemToShow'值不会被更新? – duncanhall

-1

不是你的问题的真正答案,但我发现ReactQL是一个伟大的入门工具包,为你照顾所有这些东西。它具有Apollo + React + Redux的所有样板,包括自定义的Redux缩减器。看看他们是如何做到的。