状态更改时如何防止 运行 的 useQuery?
How to prevent useQuery for running when state changes?
我正在使用 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 />
)}
/>
我正在使用反应钩子。
查看可用于完全跳过查询的 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))。
感谢@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,
};
}
如果您使用纯 apollo 客户端,您将失去 apollo 的一些功能。无需将 graphql 调用移动到 redux 操作中,您可以在 Redux 中使用选择器来防止组件重新加载或对服务器进行不必要的调用。
我正在使用 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 />
)}
/>
我正在使用反应钩子。
查看可用于完全跳过查询的 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))。
感谢@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,
};
}
如果您使用纯 apollo 客户端,您将失去 apollo 的一些功能。无需将 graphql 调用移动到 redux 操作中,您可以在 Redux 中使用选择器来防止组件重新加载或对服务器进行不必要的调用。