【发布时间】:2017-07-30 08:40:07
【问题描述】:
我正在使用 react apollo 提供的 graphql HOC 获取数据列表。例如:
const fetchList = graphql(
dataListQuery, {
options: ({ listId }) => ({
variables: {
listId,
},
}),
props: ({ data: { loading, dataList } }) => {
return {
loading,
list: dataList,
};
}
}
);
我在受控单选按钮组中显示列表,默认情况下我需要选择其中一项。选中项的id 保存在 Redux 存储中。
那么,问题是查询成功返回后如何更新Redux store(即设置selectedItem)?
我想到的一些选项:
选项 1
我应该在我的 Redux reducer 中监听 APOLLO_QUERY_RESULT 操作吗?但这有点尴尬,因为如果之前已经运行过查询,我需要同时收听APOLLO_QUERY_RESULT 和APOLLO_QUERY_RESULT_CLIENT。而且operationName 属性只出现在APOLLO_QUERY_RESULT 动作中,而不出现在APOLLO_QUERY_RESULT_CLIENT 动作中。所以我需要剖析每一个APOLLO_QUERY_RESULT_CLIENT 动作才能知道它来自哪里。难道没有一种简单直接的方法来识别查询结果操作吗?
选项 2
我是否应该在 componentWillReceiveProps 中分派像 SELECT_LIST_ITEM 这样的单独操作,例如(使用 recompose):
const enhance = compose(
connect(
function mapStateToProps(state) {
return {
selectedItem: getSelectedItem(state),
};
}, {
selectItem, // action creator
}
),
graphql(
dataListQuery, {
options: ({ listId }) => ({
variables: {
listId,
},
}),
props: ({ data: { loading, dataList } }) => ({
loading,
items: dataList,
}),
}
),
lifecycle({
componentWillReceiveProps(nextProps) {
const {
loading,
items,
selectedItem,
selectItem,
} = nextProps;
if (!selectedItem && !loading && items && items.length) {
selectItem(items[items.length - 1].id);
}
}
})
);
选项 3
我是否应该直接使用 Apollo 客户端,将其注入 withApollo,然后使用 client.query(...).then(result => { /* some logic */ selectItem(...)}) 调度我的操作。但是我会失去 react-apollo 集成的所有好处,所以不是一个真正的选择。
选项 4
查询返回后我是否应该完全不更新 Redux 存储?因为我也可以只实现一个选择器,如果它已设置,则返回 selectedItem,如果没有,它会尝试通过浏览商店的 apollo 部分来派生它。
我没有一个选择让我满意。那么,我该怎么做呢?
【问题讨论】:
-
我现在也遇到了类似的问题,你最后用的是哪个选项?
-
我目前正在使用选项 2。
-
但是选项二总是有效吗?我的印象是 componentWillReceiveProps 仅在道具更改时运行,而不一定在第一次渲染时运行。所以如果你的 props 没有发生变化,这个生命周期方法就不会运行,你的 action 也不会被调度。不过,也许我误解了该生命周期方法的语义。
-
@AdamDonahue React 文档明确指出:请注意,即使 props 没有更改,React 也可能会调用此方法,因此如果您只想处理,请确保比较当前值和下一个值变化。当父组件导致您的组件重新渲染时,可能会发生这种情况。 Docs
-
@TheWebweiser 我想你误解了。我的意思是,如果您的初始道具集永远不会改变,那么 componentWillReceiveProps 可能不会运行。这至少是我对这个生命周期方法文档的以下部分的解释:“React 在挂载期间不会使用初始道具调用 componentWillReceiveProps。它仅在某些组件的道具可能更新时才调用此方法。”那么,似乎很清楚,上面的选项 2 是不完整的。或者可以,除非您以某种方式强制更改道具。
标签: reactjs apollostack react-apollo apollo-client