如何在Apollo GraphQL查询返回后更新Redux存储

The*_*ser 23 reactjs apollostack react-apollo apollo-client

我正在graphql通过react apollo提供的HOC 获取数据列表.例如:

const fetchList = graphql(
  dataListQuery, {
    options: ({ listId }) => ({
      variables: {
        listId,
      },
    }),
    props: ({ data: { loading, dataList } }) => {
      return {
        loading,
        list: dataList,
      };
    }
  }
);
Run Code Online (Sandbox Code Playgroud)

我在受控的单选按钮组中显示列表,我需要默认选择其中一个项目.在id所选择的项目被保留在终极版商店.

那么,问题是如何selectedItem在查询成功返回后更新Redux存储(即设置)?

我想到了一些选择:

选项1

我应该APOLLO_QUERY_RESULT在Redux减速机上听动作吗?但这有点尴尬,因为那时我需要听两个APOLLO_QUERY_RESULT,APOLLO_QUERY_RESULT_CLIENT如果查询已经运行过.同时,也是operationName道具只在本APOLLO_QUERY_RESULT行动而不是APOLLO_QUERY_RESULT_CLIENT采取行动.因此,我需要剖析每一个APOLLO_QUERY_RESULT_CLIENT动作,以了解它的来源.是否有一种简单直接的方法来识别查询结果操作?

选项2

我应该发送一个单独的动作SELECT_LIST_ITEM,componentWillReceiveProps例如(使用重构):

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);
      }
    }
  })
);
Run Code Online (Sandbox Code Playgroud)

选项3

我应该直接使用Apollo客户端注入withApollo,然后发送我的操作client.query(...).then(result => { /* some logic */ selectItem(...)}).但是,我会放弃react-apollo集成的所有好处,所以不是一个真正的选择.

选项4

在查询返回后,我是否应该根本不更新Redux存储?因为我也可以只实现一个选择器,它返回selectedItem它是否已设置,如果没有,它会尝试通过浏览apollo商店的一部分来派生它.

我的选择都不能让我满意.那么,我该怎么做呢?

C.L*_*Lee 2

我会做类似于选项 2 的事情,但将生命周期方法放入实际的组件中。这样生命周期中的业务逻辑就会和继承自Container的props分离。

所以像这样:

class yourComponent extends Component{
    componentWillReceiveProps(nextProps) {
      const {
        loading,
        items,
        selectedItem,
        selectItem,
      } = nextProps;
      if (!selectedItem && !loading && items && items.length) {
        selectItem(items[items.length - 1].id);
      }
    }
  render(){...}
}

// Connect redux and graphQL to the Component
const yourComponentWithGraphQL = graphql(...)(yourComponent);
export default connect(mapStateToProps, mapDispatchToProps)(yourComponentWithGraphQL)
Run Code Online (Sandbox Code Playgroud)