Скажите, что я делаю что-то вроде этого:
import React, { useContext } from 'react';
import { useLazyQuery } from '@apollo/react-hooks';
import type { DocumentNode } from 'graphql';
import { stringifyGqlTag } from '...'; // some path, my own method
export const GqlContext = React.createContext<GqlContextT>({});
export const useGqlLazyQuery = (gqlTag: DocumentNode) => {
return useContext(GqlContext)[stringifyGqlTag(gqlTag)];
};
export const GqlContextProvider = ({ children }: { children: React$Node }) => {
const value = {
[FOO_GQL_STRING]: useLazyQuery(FOO_GQL),
[BAR_GQL_STRING]: useLazyQuery(BAR_GQL),
// ...
// This could be a lot since we're going to have all the `useLazyQuery` within the app here.
// Could easily reach 50+, really depends on how big the app is...
};
return <GqlContext.Provider value={value}>{children}</GqlContext.Provider>;
};
--------------------------------------------
// In some other file, we have the gql stuff
import gql from 'graphql-tag';
import { stringifyGqlTag } from '...'; // some path, my own method
export const FOO_GQL = gql`...`;
export const FOO_GQL_STRING = stringifyGqlTag(FOO_GQL);
...
Использование его в компонентах:
const Foo = () => {
const [fetchData] = useGqlLazyQuery(FOO_GQL);
useEffect(() => fetchData(), []);
return <div>...</div>;
};
// Then in another component, maybe sibling, or deep child component
const SomeComponent = () => {
// Yey, I have access to loading, data, and error here!
const [, { loading, data, error }] = useGqlLazyQuery(FOO_GQL);
// We can now do conditional render based on loading and error.
};
Почему я это делаю?
В основном я просто хочу иметь возможность читать состояние загрузки и ошибок из любого компонента в моем приложении. Я смог добиться этого с помощью Redux, но это слишком много, в результате чего два хранилища данных каким-то образом, один внутри клиента Apollo, а другой в Redux. Таким образом, это пустая трата.
Когда я использую apolloClient.readQuery
, я могу читать только data
, но не loading
и error
.
Выполнение этого шаблона синглтона Я могу читать data
, loading
и error
из любого места в приложении, исключая использование избыточности.
1. Учитывая этот контекст, каковы недостатки этого?
Я не так много сделал GraphQL, поэтому я не имею в виду много реальных вариантов использования. Единственное, о чем я мог подумать, это:
// Say you need to fetch multiple FOO. I don't know, maybe you have a "compare" page.
const [fetchFoo1, { data: data1, loading: loading1, error: error1 }] = useGqlLazyQuery(FOO_GQL);
const [fetchFoo2, { data: data2, loading: loading2, error: error2 }] = useGqlLazyQuery(FOO_GQL);
// This won't work because data1 and data2 will just point to the same one.
// Same goes for loading1 and loading2, as well as error1 and error2, they're all point to the same value.
// So, in this particular case, we just need to go back to use the original `useLazyQuery`.
2. Каковы преимущества этого? Если есть:)
3. Как сохранить состояние loading
и error
в приложении, чтобы вы могли получить к ним доступ из любого места в приложении?