使用 Apollo 客户端时在 Redux 中调度操作会导致 Apollo 客户端重置查询

Posted

技术标签:

【中文标题】使用 Apollo 客户端时在 Redux 中调度操作会导致 Apollo 客户端重置查询【英文标题】:Dispatching actions in Redux while using Apollo Client causes Apollo client to reset query 【发布时间】:2018-02-09 21:36:09 【问题描述】:

我有一个 TypeAhead 组件。当用户进入组件页面时,Apollo 会拉取 5 个玩家的初始查询,用于预先输入。理想情况下,我想跳过这个初始查询,但这完全是另一回事。所以查询中填充了 5 个玩家。 Player1 到 Player5,当我开始输入预输入搜索 Player10 时,我选择 Player10 并调度一个动作以使其成为当前选择的 Player。但是,在我触发 onBlur 或离开该框后,Apollo 调度了 APOLLO_QUERY_RESULT_CLIENT 的 Redux 操作,它将所有 typeAhead 设置回 Player1 到 Player5 我的初始查询,而不是将其正确设置为 Player10。你如何防止 APOLLO_QUERY_RESULT_CLIENT 在我调度我自己创建的动作时调度。

class TypeAhead extends Component 
  constructor() 
    super();

    this.state = 
      value: ''
    ;
  

  renderInputComponent = (inputProps) => 
    let selectedSuggestion = this.props;
    return (
      <div className="inputContainer">
        <img className="type-ahead__image"  src=getImageURL(selectedSuggestion.id) />
        <TextField floatingLabelText="Search Player" ...inputProps />
      </div>
    )
  

  onChange = (event,  newValue ) => 
    this.setState(
      value: newValue
    );
  ;

  shouldRenderSuggestions(value) 
    return value.trim().length > MIN_SEARCH_LENGTH;
  

  onSuggestionsFetchRequested = ( value ) => 
    // debugger;
    if(/^[a-z .,-]+$/i.test(value)) 
      this.props.data.refetch(name: value);
    
  ;

  onSuggestionsClearRequested = () => 
    // debugger;
    // this.setState(
    //   suggestions: []
    // );
    // this.props.data.Players = [];
  ;

  onBlur = () => 
    if (this.state.value.toLowerCase() === this.props.data.Players[0].name.toLowerCase()) 
      let suggestion = this.props.data.Players[0];
      this.props.onSuggestionSelected(null,  suggestion );
     
  

  render() 
    console.log(this.props.data.Players)
    let suggestions = this.props.data.Players || [];
    let  onSuggestionSelected  = this.props;
    let  value  = this.state;
    let inputProps = 
      value,
      onChange: this.onChange,
      onBlur: this.onBlur
    ;

    return (
      <div>
        <Autosuggest
          suggestions=suggestions
          onSuggestionsFetchRequested=this.onSuggestionsFetchRequested
          onSuggestionsClearRequested=this.onSuggestionsClearRequested
          getSuggestionValue=getSuggestionValue
          renderSuggestion=renderSuggestion
          shouldRenderSuggestions=this.shouldRenderSuggestions
          onSuggestionSelected=onSuggestionSelected
          renderInputComponent=this.renderInputComponent
          inputProps=inputProps 
          />
      </div>
    );
  


const mapStateToProps = (state) => 
  return 
    selectedSuggestion: state.selectedSuggestion
  


const mapDispatchToProps = (dispatch) => 
  return 
    onSuggestionSelected(event, suggestion) 
      dispatch(actions.selectSuggestion(suggestion));
      // dispatching action causes apollo to requery and pull inital query causing issues.
    ,
    onSuggestionUnselected() 
      dispatch(actions.unselectSuggestion());
    
  


const TypeAheadWithData = graphql(TypeAheadQuery, 
  options: ( name ) => ( variables:  name  )
)(TypeAhead);
const TypeAheadWithDataAndState = connect(mapStateToProps, mapDispatchToProps)(TypeAheadWithData);
export default TypeAheadWithDataAndState;

【问题讨论】:

【参考方案1】:
const TypeAheadWithData = graphql(TypeAheadQuery, 
  options: ( name ) => ( variables:  name  )
)(TypeAhead);

只要 name 属性发生变化,查询就会再次运行。您很可能在再次运行查询之前重置了名称。

如果不是这样,你可以通过调试networkStatus 知道为什么graphql 容器正在重新获取。还需要加options: notifyOnNetworkStatusChange: true

【讨论】:

是的,我手动向它发送了一个带有 name 属性的 refetch。所以这可能是它运行了两次。 this.props.data.refetch(name: value); 由于组件本身正在接收一个状态,如果我访问道具并通过 this.props.variables.name 更改它会触发重新获取,它需要更新?

以上是关于使用 Apollo 客户端时在 Redux 中调度操作会导致 Apollo 客户端重置查询的主要内容,如果未能解决你的问题,请参考以下文章

React Apollo 查询返回后调度 Redux 操作

在 apollo-react 查询后调度 redux 操作

如何使用 Apollo 在后台执行查询?

如何使用 GraphQL 的 Apollo 客户端将获取的数据存储到 Redux 的存储中

Apollo 客户端缓存与 Redux

使用多个中间件时在 redux 存储上正确键入 dispatch