Skip to content
This repository was archived by the owner on Apr 13, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Fix React.createContext in SSR
diff --git a/src/getDataFromTree.ts b/src/getDataFromTree.ts
index 8008f09..cc731fb 100755
--- a/src/getDataFromTree.ts
+++ b/src/getDataFromTree.ts
@@ -140,8 +140,14 @@ export function walkTree(
         return;
       }

+      let isProvider = !!(element.type as any)._context;
+      let previousContextValue: any;
+      if (isProvider) {
+        previousContextValue = ((element.type as any)._context as any)._currentValue;
+      }
+
       let child;
-      if ((element.type as any)._context) {
+      if (isProvider) {
         // A provider - sets the context value before rendering children
         ((element.type as any)._context as any)._currentValue = element.props.value;
         child = element.props.children;
@@ -157,6 +163,9 @@ export function walkTree(
           walkTree(child, context, visitor);
         }
       }
+      if (isProvider) {
+        ((element.type as any)._context as any)._currentValue = previousContextValue;
+      }
     } else {
       // A basic string or dom element, just get children
       if (visitor(element, null, context) === false) {
diff --git a/test/server/server.test.tsx b/test/server/server.test.tsx
index 9b2c93c..96bd196 100644
--- a/test/server/server.test.tsx
+++ b/test/server/server.test.tsx
@@ -262,5 +262,32 @@ describe('SSR', () => {
         expect(markup).toMatch(/Tatooine/);
       });
     });
+    it('should work with React.createContext', async () => {
+      let defaultValue = 'default';
+      let Context = React.createContext(defaultValue);
+
+      let providerValue = 'provider';
+
+      expect(
+        await renderToStringWithData(
+          <React.Fragment>
+            <Context.Provider value={providerValue} />
+            <Context.Consumer>{val => val}</Context.Consumer>
+          </React.Fragment>,
+        ),
+      ).toBe('default');
+
+      expect(
+        await renderToStringWithData(
+          <Context.Provider value={providerValue}>
+            <Context.Consumer>{val => val}</Context.Consumer>
+          </Context.Provider>,
+        ),
+      ).toBe(providerValue);
+
+      expect(await renderToStringWithData(<Context.Consumer>{val => val}</Context.Consumer>)).toBe(
+        defaultValue,
+      );
+    });
   });
 });
  • Loading branch information
emmatown committed Aug 24, 2018
commit ae37aaa31e322a6f030096063471b3277ae48b56
11 changes: 10 additions & 1 deletion src/getDataFromTree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,14 @@ export function walkTree(
return;
}

let isProvider = !!(element.type as any)._context;
let previousContextValue: any;
if (isProvider) {
previousContextValue = ((element.type as any)._context as any)._currentValue;
}

let child;
if ((element.type as any)._context) {
if (isProvider) {
// A provider - sets the context value before rendering children
((element.type as any)._context as any)._currentValue = element.props.value;
child = element.props.children;
Expand All @@ -157,6 +163,9 @@ export function walkTree(
walkTree(child, context, visitor);
}
}
if (isProvider) {
((element.type as any)._context as any)._currentValue = previousContextValue;
}
} else {
// A basic string or dom element, just get children
if (visitor(element, null, context) === false) {
Expand Down
27 changes: 27 additions & 0 deletions test/server/server.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -262,5 +262,32 @@ describe('SSR', () => {
expect(markup).toMatch(/Tatooine/);
});
});
it('should work with React.createContext', async () => {
let defaultValue = 'default';
let Context = React.createContext(defaultValue);

let providerValue = 'provider';

expect(
await renderToStringWithData(
<React.Fragment>
<Context.Provider value={providerValue} />
<Context.Consumer>{val => val}</Context.Consumer>
</React.Fragment>,
),
).toBe('default');

expect(
await renderToStringWithData(
<Context.Provider value={providerValue}>
<Context.Consumer>{val => val}</Context.Consumer>
</Context.Provider>,
),
).toBe(providerValue);

expect(await renderToStringWithData(<Context.Consumer>{val => val}</Context.Consumer>)).toBe(
defaultValue,
);
});
});
});