ESLint жалуется на валидацию реквизита даже с определенным propTypes - PullRequest
0 голосов
/ 04 октября 2019

Взгляните на это:

/* eslint no-console: 0 */
import { ApolloProvider } from '@apollo/react-hooks';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { ApolloClient } from 'apollo-client';
import { HttpLink } from 'apollo-link-http';
import fetch from 'isomorphic-unfetch';
import Head from 'next/head';
import { useMemo } from 'react';
import PropTypes from 'prop-types';

let apolloClient = null;

/**
 * Creates and configures the ApolloClient
 * @param  {Object} [initialState={}]
 */
// Check out https://github.com/zeit/next.js/pull/4611 if you want to use the AWSAppSyncClient
const createApolloClient = (initialState = {}) => new ApolloClient({
  ssrMode: typeof window === 'undefined', // Disables forceFetch on the server (so queries are only run once)
  link: new HttpLink({
    uri: process.env.CMS, // Server URL (must be absolute)
    credentials: 'same-origin', // Additional fetch() options like `credentials` or `headers`
    headers: {
      // Get JWT from Strapi Admin -> Plugins -> Documentation -> Retrieve your jwt token
      authorization: `Bearer ${process.env.STRAPI_TOKEN}`,
    },
    fetch,
  }),
  cache: new InMemoryCache().restore(initialState),
});

/**
 * Always creates a new apollo client on the server
 * Creates or reuses apollo client in the browser.
 * @param  {Object} initialState
 */
const initApolloClient = (initialState) => {
  // Make sure to create a new client for every server-side request so that data
  // isn't shared between connections (which would be bad)
  if (typeof window === 'undefined') {
    return createApolloClient(initialState);
  }

  // Reuse client on the client-side
  if (!apolloClient) {
    apolloClient = createApolloClient(initialState);
  }

  return apolloClient;
};

/**
 * Creates and provides the apolloContext
 * to a next.js PageTree. Use it by wrapping
 * your PageComponent via HOC pattern.
 * @param {Function|Class} PageComponent
 * @param {Object} [config]
 * @param {Boolean} [config.ssr=true]
 */
const withApollo = (PageComponent, { ssr = true } = {}) => {
  const WithApollo = ({ apolloClient, apolloState, ...pageProps }) => {
    const client = useMemo(
      () => apolloClient || initApolloClient(apolloState),
      [apolloClient, apolloState],
    );
    return (
      <ApolloProvider client={client}>
        <PageComponent {...pageProps} />
      </ApolloProvider>
    );
  };

  // Set the correct displayName in development
  if (process.env.NODE_ENV !== 'production') {
    const displayName = PageComponent.displayName || PageComponent.name || 'Component';

    if (displayName === 'App') {
      console.warn('This withApollo HOC only works with PageComponents.');
    }

    WithApollo.displayName = `withApollo(${displayName})`;
  }

  if (ssr || PageComponent.getInitialProps) {
    WithApollo.getInitialProps = async (ctx) => {
      const { AppTree } = ctx;

      // Initialize ApolloClient, add it to the ctx object so
      // we can use it in `PageComponent.getInitialProp`.
      ctx.apolloClient = initApolloClient();
      const { apolloClient } = ctx;

      // Run wrapped getInitialProps methods
      let pageProps = {};
      if (PageComponent.getInitialProps) {
        pageProps = await PageComponent.getInitialProps(ctx);
      }

      // Only on the server:
      if (typeof window === 'undefined') {
        // When redirecting, the response is finished.
        // No point in continuing to render
        if (ctx.res && ctx.res.finished) {
          return pageProps;
        }

        // Only if ssr is enabled
        if (ssr) {
          try {
            // Run all GraphQL queries
            const { getDataFromTree } = await import('@apollo/react-ssr');
            await getDataFromTree(
              <AppTree
                pageProps={{
                  ...pageProps,
                  apolloClient,
                }}
              />,
            );
          } catch (error) {
            // Prevent Apollo Client GraphQL errors from crashing SSR.
            // Handle them in components via the data.error prop:
            // https://www.apollographql.com/docs/react/api/react-apollo.html#graphql-query-data-error
            console.error('Error while running `getDataFromTree`', error);
          }

          // getDataFromTree does not call componentWillUnmount
          // head side effect therefore need to be cleared manually
          Head.rewind();
        }
      }

      // Extract query data from the Apollo store
      const apolloState = apolloClient.cache.extract();

      return {
        ...pageProps,
        apolloState,
      };
    };
  }

  return WithApollo;
};

withApollo.propTypes = {
  apolloClient: PropTypes.string.isRequired,
  apolloState: PropTypes.string.isRequired,
};

export default withApollo;

Как видите, в моем коде есть следующие строки:

import PropTypes from 'prop-types';

и

withApollo.propTypes = {
  apolloClient: PropTypes.string.isRequired,
  apolloState: PropTypes.string.isRequired,
};

И все же ESLint не может распознать это и выдает эту ошибку:

  2:1   error  Run autofix to sort these imports!                     simple-import-sort/sort
  61:25  error  'apolloClient' is already declared in the upper scope  no-shadow
  61:25  error  'apolloClient' is missing in props validation          react/prop-types
  61:39  error  'apolloState' is missing in props validation           react/prop-types
  91:15  error  'apolloClient' is already declared in the upper scope  no-shadow

Почему? Почему говорят, что apolloClient и apolloState отсутствуют в проверке реквизита, когда я четко убедился, что это не так? Я знаю, что могу просто подавить это с помощью /* eslint react/prop-types: 0 */, но я не хочу этого делать. Я просто хочу понять, чего мне здесь не хватает.

...