Repository: facebook/react
File: packages/react/src/ReactFetch.js (JavaScript)

Code before:
      if (
        options &&
        options.signal &&
        options.signal !== dispatcher.getCacheSignal()
      ) {
        // If we're passed a signal that is not ours, then we assume that
        // someone else controls the lifetime of this object and opts out of
        // caching. It's effectively the opt-out mechanism.
        // Ideally we should be able to check this on the Request but
        // it always gets initialized with its own signal so we don't
        // know if it's supposed to override - unless we also override the
        // Request constructor.
        return originalFetch(resource, options);
      }
      // Normalize the Request
      let url: string;
      let cacheKey: string;
      if (typeof resource === 'string' && !options) {
        // Fast path.
        cacheKey = simpleCacheKey;
        url = resource;
      } else {
        // Normalize the request.
        // if resource is not a string (its an instance of Request)
        // we clone the request as to not disturb the body (in the event it's a ReadableStream)
        const request = typeof resource === 'string' ? new Request(resource, options) : resource.clone();
        if (
          (request.method !== 'GET' && request.method !== 'HEAD') ||
          // $FlowFixMe[prop-missing]: keepalive is real
          request.keepalive
        ) {
          // We currently don't dedupe requests that might have side-effects. Those
          // have to be explicitly cached. We assume that the request doesn't have a
          // body if it's GET or HEAD.
          // keepalive gets treated the same as if you passed a custom cache signal.
          return originalFetch(resource, options);
        }
        cacheKey = generateCacheKey(request);
        url = request.url;
      }
      const cache = dispatcher.getCacheForType(createFetchCache);
      const cacheEntries = cache.get(url);
      let match;
      if (cacheEntries === undefined) {
        // We pass the original arguments here in case normalizing the Request
        // doesn't include all the options in this environment.
        match = originalFetch(resource, options);
        cache.set(url, [cacheKey, match]);
      } else {
        // We use an array as the inner data structure since it's lighter and
        // we typically only expect to see one or two entries here.

Review comment (suggestion):
It seems better to just let the request pass through in this case instead of cloning it.

The normalization is more about turning the string case into a request so we can get the right keys.

Code after:
      if (
        options &&
        options.signal &&
        options.signal !== dispatcher.getCacheSignal()
      ) {
        // If we're passed a signal that is not ours, then we assume that
        // someone else controls the lifetime of this object and opts out of
        // caching. It's effectively the opt-out mechanism.
        // Ideally we should be able to check this on the Request but
        // it always gets initialized with its own signal so we don't
        // know if it's supposed to override - unless we also override the
        // Request constructor.
        return originalFetch(resource, options);
      }
      // Normalize the Request
      let url: string;
      let cacheKey: string;
      if (typeof resource === 'string' && !options) {
        // Fast path.
        cacheKey = simpleCacheKey;
        url = resource;
      } else {
        // Normalize the request.
        // if resource is not a string or a URL (its an instance of Request)
        // then do not instantiate a new Request but instead
        // reuse the request as to not disturb the body in the event it's a ReadableStream.
        const request =
          typeof resource === 'string' || resource instanceof URL
            ? new Request(resource, options)
            : resource;
        if (
          (request.method !== 'GET' && request.method !== 'HEAD') ||
          // $FlowFixMe[prop-missing]: keepalive is real
          request.keepalive
        ) {
          // We currently don't dedupe requests that might have side-effects. Those
          // have to be explicitly cached. We assume that the request doesn't have a
          // body if it's GET or HEAD.
          // keepalive gets treated the same as if you passed a custom cache signal.
          return originalFetch(resource, options);
        }
        cacheKey = generateCacheKey(request);
        url = request.url;
      }
      const cache = dispatcher.getCacheForType(createFetchCache);
      const cacheEntries = cache.get(url);
      let match;
      if (cacheEntries === undefined) {
        // We pass the original arguments here in case normalizing the Request
        // doesn't include all the options in this environment.
        match = originalFetch(resource, options);