Repository: facebook/react
Pull request: Reuse request so that a ReadableStream body does not become disturbed

<!--
  Thanks for submitting a pull request!
  We appreciate you spending the time to work on these changes. Please provide enough information so that others can review your pull request. The three fields below are mandatory.

  Before submitting a pull request, please make sure the following is done:

  1. Fork [the repository](https://github.com/facebook/react) and create your branch from `main`.
  2. Run `yarn` in the repository root.
  3. If you've fixed a bug or added code that should be tested, add tests!
  4. Ensure the test suite passes (`yarn test`). Tip: `yarn test --watch TestName` is helpful in development.
  5. Run `yarn test --prod` to test in the production environment. It supports the same options as `yarn test`.
  6. If you need a debugger, run `yarn test --debug --watch TestName`, open `chrome://inspect`, and press "Inspect".
  7. Format your code with [prettier](https://github.com/prettier/prettier) (`yarn prettier`).
  8. Make sure your code lints (`yarn lint`). Tip: `yarn linc` to only check changed files.
  9. Run the [Flow](https://flowtype.org/) type checks (`yarn flow`).
  10. If you haven't already, complete the CLA.

  Learn more about contributing: https://reactjs.org/docs/how-to-contribute.html
-->

## Summary

* this fixes https://github.com/vercel/next.js/issues/49144

## How did you test this change?

* I ran `yarn test`

```bash
Test Suites: 2 skipped, 295 passed, 295 of 297 total
Tests:       92 skipped, 7824 passed, 7916 total
Snapshots:   177 passed, 177 total
Time:        121.105 s
Ran all test suites.
✨  Done in 124.21s.
```


Changed files:
filename: packages/react/src/ReactFetch.js
patch: @@ -74,7 +74,13 @@ if (enableCache && enableFetchInstrumentation) {
         url = resource;
       } else {
         // Normalize the request.
-        const request = new Request(resource, options);
+        // 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

filename: packages/react/src/__tests__/ReactFetch-test.js
patch: @@ -135,6 +135,22 @@ describe('ReactFetch', () => {
     expect(fetchCount).toBe(1);
   });
 
+  // @gate enableFetchInstrumentation && enableCache
+  it('can dedupe fetches using URL and not', async () => {
+    const url = 'http://example.com/';
+    function Component() {
+      const response = use(fetch(url));
+      const text = use(response.text());
+      const response2 = use(fetch(new URL(url)));
+      const text2 = use(response2.text());
+      return text + ' ' + text2;
+    }
+    expect(await render(Component)).toMatchInlineSnapshot(
+      `"GET ${url} [] GET ${url} []"`,
+    );
+    expect(fetchCount).toBe(1);
+  });
+
   it('can opt-out of deduping fetches inside of render with custom signal', async () => {
     const controller = new AbortController();
     function useCustomHook() {