React-admin:登录后 useQuery 未在仪表板上获取数据

React-admin: useQuery not fetching data on Dashboard after logging in

我已经使用 GraphQL 设置了 react-admin 并且在大多数情况下工作正常......但是最初登录并让 Dashboard 进行查询似乎有问题;问题是它不会在初始加载时解决。它从登录 -> 仪表板开始,我遇到了一个永远加载的组件,没有 dataerrors.

我的Admin是这样设置的:

const routes = [
    <Route exact path="/support-chat-list" component={SupportChatPage} noLayout />,
    <Route exact path="/group-chat" component={GroupChatPage} noLayout />,
    <Route exact path="/" component={Dashboard} />,
];

const App = () => (
    <Admin dashboard={Dashboard} layout={MyLayout} customRoutes={routes} dataProvider={dataProvider} authProvider={authProvider} i18nProvider={i18nProvider}>
        {/* my resources... */}
    </Admin>
);

我的 Dashboard 看起来像这样:

const requestOptions = (startingAfter, startingBefore) => {
    return {
        type    : 'getList',
        resource: 'appointments',
        payload : {
            pagination: {
                perPage: 100,
                page   : 0,
            },
            sort      : {
                field: 'start_at',
                order: 'asc'
            },
            filter    : {
                startingAfter: startingAfter.toString(),
                startingBefore: startingBefore.toString(),
            }
        }
    };
};

const handleSelectEvent = (event, e, redirectTo) => {
    redirectTo('show', ROUTES.APPOINTMENTS, event.resource.id);
};

const initialState = {
    middleDate: DateTime.local().startOf('day'),
    startDate: DateTime.local().minus({days: 3}).startOf('day'),
    endDate: DateTime.local().plus({days: 3}).endOf('day'),
};

export function Dashboard() {
    useAuthenticated();
    const redirectTo = useRedirect();
    const [dateRanges, setDateRanges] = useState(initialState);
    const {data, loading, error} = useQueryWithStore(requestOptions(dateRanges.startDate, dateRanges.endDate));

    if (error) return <Error />;

    return (
        <Card>
            <Title title="Admin" />
            <CardContent>
                {loading && <Loading/>}
                {!loading &&
                    <Calendar
                        events={translateAppointmentData(data)}
                        //.......

我试过 useQueryuseQueryWithStore 但似乎没有任何效果。 它只会在我刷新页面时解决,然后才会加载所有内容。

我怀疑这与我的 authProvider 有关,这是一个处理身份验证的 class。有点臃肿所以我会尽力展示与login相关的东西:

async login({username, password}) {
        const response = await authClient.passwordGrant(username, password, ACCESS_TOKEN_SCOPES);
        await this.processTokenResponse(response);

        return Promise.resolve();
    }

authClient.passwordGrant 看起来像这样:

passwordGrant(username, password, scopes) {
        const request = new Request(`${this.url}/oauth/access_token`, {
            method: 'POST',
            body: JSON.stringify({
                username: username,
                password: password,
                client_id: this.clientId,
                client_secret: this.clientSecret,
                grant_type: 'password',
                scope: scopes.join(' '),
            }),
            headers: new Headers({ 'Content-Type': 'application/json' }),
        });

        return fetch(request)
            .then(response => {
                if (response.status < 200 || response.status >= 300) {
                    throw new Error(response.statusText);
                }

                return response.json();
            });
    }

processTokenResponse 看起来像这样:

processTokenResponse(response) {
        const now = DateTime.local();
        localStorage.setItem(TOKEN_STORAGE_KEY, response.access_token);
        localStorage.setItem(TOKEN_EXPIRY_STORAGE_KEY, now.plus({seconds: response.expires_in - EXPIRY_BUFFER}).toString());

        localStorage.setItem(SCOPES_STORAGE_KEY, JSON.stringify({scopes: response.scopes}));

        localStorage.setItem(REFRESH_TOKEN_STORAGE_KEY, response.refresh_token);
        localStorage.setItem(REFRESH_TOKEN_EXPIRY_STORAGE_KEY, now.plus({seconds: response.refresh_token_expires_in - EXPIRY_BUFFER}).toString());

        return this.fetchActiveUserData();
    }

fetchActiveUserData 看起来像这样:

async fetchActiveUserData() {
        let dataProvider = new ActiveUserDataProvider();

        return await dataProvider.getOne({}).then((response) => {
            return this.processLoadUserResponse(response.data);
        })
    }

其中我的 dataProvider 如下所示:

import apolloClient from '../apolloClient';
import { BaseResourceDataProvider } from './baseResourceDataProvider';
import {FetchMeQuery} from "../graphql/users";

const FetchMeQuery = gql`
    query FetchMe {
        me {
            id
            firstName
            lastName
            name
            username
            timezone
        }
    }
`;

class ActiveUserDataProvider extends BaseResourceDataProvider {
    getOne({ id }: { id?: string }) { // maybe something wrong here?
        return apolloClient.query({
            query: FetchMeQuery,
            fetchPolicy: 'cache-first'
        }).then((result) => {
            return {
                data: result.data.me,
            };
        });
    }
}

我为这么长的时间道歉 post 但我完全不明白为什么我的 Dashboard 在最初登录后不查询数据,并且需要刷新才能工作。我希望有人能指出哪里出了问题。谢谢。

经过大量挖掘,结果证明这是我设置 ApolloClient 的方式。之前我使用 Apollo Link 设置我的 auth 中间件,发现它根本没有调用中间件。

我发现了 并用 setContext 替换了 ApolloLink 并且效果很好。这是现在的代码:

const authMiddleware = setContext(async (_, { headers }) => {
    const token = await authProvider.checkAuth();

    return {
        headers: {
            ...headers,
            authorization: token ? `Bearer ${token}` : '',
        }
    }
});

const apolloClient = new ApolloClient({
    cache: new InMemoryCache(),
    link: from([
        authMiddleware,
        httpLink
    ]),
});