状态变化时如何防止 useQuery 运行?

Posted

技术标签:

【中文标题】状态变化时如何防止 useQuery 运行?【英文标题】:How to prevent useQuery for running when state changes? 【发布时间】:2020-07-03 02:03:52 【问题描述】:

我正在使用 React Apollo 从我的服务器获取数据。当我的页面加载时,我使用 useQuery 来检索数据。这工作正常。问题是当我对搜索表单进行更改时,这会更新导致不需要的重新渲染并再次调用服务器的状态。

我只想在页面加载和单击搜索按钮时调用服务器。

使用查询:

const  loading: loadingLessons, error: lessonsError, data: lessons  = useQuery(
 LESSON_BY_PARAMS,
    
      variables:  findLessonsInput: searchParams ,
    ,
);

当我更改表单字段时,它会调用 updateFormField 来更新导致重新渲染的 redux 状态

<Autocomplete
  options=categories
  getOptionLabel=(option: any) => option.label
  inputValue=form.category
  defaultValue=() => 
    const value = categories.find(option => option.label === form.category);
    return value;
  
  onChange=(event, value) => updateFormField('category', value?.label)
  renderInput=params => (
    <TextField ...params label="Category" variant="outlined" fullWidth />
  )
/>

我正在使用反应钩子。

【问题讨论】:

【参考方案1】:

查看skip 选项,该选项可用于完全跳过查询。你可以这样做:

const [skip, setSkip] = React.useState(false)
const  loading, data  = useQuery(QUERY,  skip )

React.useEffect(() => 
  // check whether data exists
  if (!loading && !!data) 
    setSkip(true)
  
, [data, loading])

因此,一旦数据返回,您只需将跳过选项设置为 true。如果你想发出请求,你应该在搜索按钮上处理 onClick(只需 setSkip(false))。

【讨论】:

【参考方案2】:

如果您使用纯 apollo 客户端,您将失去 apollo 的一些功能。无需将 graphql 调用移动到 redux 操作中,您可以在 Redux 中使用选择器来防止组件重新加载或对服务器进行不必要的调用。

Selectors in Redux

【讨论】:

【参考方案3】:

感谢@Vadim Sheremetov 的建议,但我决定将 api 调用移至 redux-thunk 函数:

当页面加载时,我发送一个动作,传递它搜索参数和 apollo 客户端:

const client = useApolloClient();

useEffect(() => 
    loadLessons(searchParams, client);
, [location.search]);

const mapDispatchToProps = dispatch => 
  return 
    loadLessons: (searchParams, client) =>
      dispatch(loadLessonsAction(searchParams, client)),
  ;
;

该操作调用一个 redux thunk 函数,然后调度另一个更新状态的操作:

actions.ts:

export function loadLessonsAction(searchParams: any, client: ApolloClient<object>): 
any 
  return async function(dispatch) 
    try 
      const  data  = await client.query(
        query: LESSON_BY_PARAMS,
        variables:  findLessonsInput: searchParams ,
      );
      dispatch(loadLessonsSuccessAction(data.lessonsByParams));
     catch (error) 
  ;


export function loadLessonsSuccessAction(lessons: any[]): FilterPanelActionTypes 
  return 
    type: LOAD_LESSONS_SUCCESS,
    payload: lessons,
  ;

reducer.ts:

case LOAD_LESSONS_SUCCESS: 
  return 
    ...state,
    lessons: action.payload.lessons,
    lessonCount: action.payload.count,
  ;

【讨论】:

以上是关于状态变化时如何防止 useQuery 运行?的主要内容,如果未能解决你的问题,请参考以下文章

如何防止 Apollo 客户端 useQuery 中的错误传播?

复选框状态发生变化时如何防止页面跳转?

状态变化时如何防止 FlatList 重新渲染

如何使用 Apollo 客户端 useQuery 钩子防止不必要的重新获取?

当蓝牙连接状态发生变化时,防止onDestroy

当特定的弹簧配置文件处于活动状态时,如何防止运行测试?