状态变化时如何防止useQuery运行-React,Apollo,GraphQL

时间:2020-03-22 12:46:37

标签: reactjs react-redux react-apollo

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

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

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 />
  )}
/>

我正在使用反应钩子。

3 个答案:

答案 0 :(得分:4)

看看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])

因此,一旦返回数据,您只需将skip选项设置为true。如果要发出请求,则应处理搜索按钮上的onClick(只需setSkip(false))。

答案 1 :(得分:0)

感谢@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,
  };
}

答案 2 :(得分:0)

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

Selectors in Redux