Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit fa65c58

Browse files
authored
Add readContext to SSR (facebook#13888)
Will be used by react-cache.
1 parent d9a3cc0 commit fa65c58

File tree

2 files changed

+94
-37
lines changed

2 files changed

+94
-37
lines changed

packages/react-dom/src/__tests__/ReactServerRendering-test.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
let React;
1414
let ReactDOMServer;
1515
let PropTypes;
16+
let ReactCurrentOwner;
1617

1718
function normalizeCodeLocInfo(str) {
1819
return str && str.replace(/\(at .+?:\d+\)/g, '(at **)');
@@ -24,6 +25,9 @@ describe('ReactDOMServer', () => {
2425
React = require('react');
2526
PropTypes = require('prop-types');
2627
ReactDOMServer = require('react-dom/server');
28+
ReactCurrentOwner =
29+
React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED
30+
.ReactCurrentOwner;
2731
});
2832

2933
describe('renderToString', () => {
@@ -431,6 +435,44 @@ describe('ReactDOMServer', () => {
431435
expect(results).toEqual([2, 1, 3, 1]);
432436
});
433437

438+
it('renders with dispatcher.readContext mechanism', () => {
439+
const Context = React.createContext(0);
440+
441+
function readContext(context) {
442+
return ReactCurrentOwner.currentDispatcher.readContext(context);
443+
}
444+
445+
function Consumer(props) {
446+
return 'Result: ' + readContext(Context);
447+
}
448+
449+
const Indirection = React.Fragment;
450+
451+
function App(props) {
452+
return (
453+
<Context.Provider value={props.value}>
454+
<Context.Provider value={2}>
455+
<Consumer />
456+
</Context.Provider>
457+
<Indirection>
458+
<Indirection>
459+
<Consumer />
460+
<Context.Provider value={3}>
461+
<Consumer />
462+
</Context.Provider>
463+
</Indirection>
464+
</Indirection>
465+
<Consumer />
466+
</Context.Provider>
467+
);
468+
}
469+
470+
const markup = ReactDOMServer.renderToString(<App value={1} />);
471+
// Extract the numbers rendered by the consumers
472+
const results = markup.match(/\d+/g).map(Number);
473+
expect(results).toEqual([2, 1, 3, 1]);
474+
});
475+
434476
it('renders context API, reentrancy', () => {
435477
const Context = React.createContext(0);
436478

packages/react-dom/src/server/ReactPartialRenderer.js

Lines changed: 52 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ const toArray = ((React.Children.toArray: any): toArrayType);
7575
// Each stack is an array of frames which may contain nested stacks of elements.
7676
let currentDebugStacks = [];
7777

78+
let ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner;
7879
let ReactDebugCurrentFrame;
7980
let prevGetCurrentStackImpl = null;
8081
let getCurrentServerStackImpl = () => '';
@@ -85,6 +86,15 @@ let pushCurrentDebugStack = (stack: Array<Frame>) => {};
8586
let pushElementToDebugStack = (element: ReactElement) => {};
8687
let popCurrentDebugStack = () => {};
8788

89+
let Dispatcher = {
90+
readContext<T>(
91+
context: ReactContext<T>,
92+
observedBits: void | number | boolean,
93+
): T {
94+
return context._currentValue;
95+
},
96+
};
97+
8898
if (__DEV__) {
8999
ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame;
90100

@@ -787,49 +797,54 @@ class ReactDOMServerRenderer {
787797
return null;
788798
}
789799

790-
let out = '';
791-
while (out.length < bytes) {
792-
if (this.stack.length === 0) {
793-
this.exhausted = true;
794-
break;
795-
}
796-
const frame: Frame = this.stack[this.stack.length - 1];
797-
if (frame.childIndex >= frame.children.length) {
798-
const footer = frame.footer;
799-
out += footer;
800-
if (footer !== '') {
801-
this.previousWasTextNode = false;
800+
ReactCurrentOwner.currentDispatcher = Dispatcher;
801+
try {
802+
let out = '';
803+
while (out.length < bytes) {
804+
if (this.stack.length === 0) {
805+
this.exhausted = true;
806+
break;
802807
}
803-
this.stack.pop();
804-
if (frame.type === 'select') {
805-
this.currentSelectValue = null;
806-
} else if (
807-
frame.type != null &&
808-
frame.type.type != null &&
809-
frame.type.type.$$typeof === REACT_PROVIDER_TYPE
810-
) {
811-
const provider: ReactProvider<any> = (frame.type: any);
812-
this.popProvider(provider);
808+
const frame: Frame = this.stack[this.stack.length - 1];
809+
if (frame.childIndex >= frame.children.length) {
810+
const footer = frame.footer;
811+
out += footer;
812+
if (footer !== '') {
813+
this.previousWasTextNode = false;
814+
}
815+
this.stack.pop();
816+
if (frame.type === 'select') {
817+
this.currentSelectValue = null;
818+
} else if (
819+
frame.type != null &&
820+
frame.type.type != null &&
821+
frame.type.type.$$typeof === REACT_PROVIDER_TYPE
822+
) {
823+
const provider: ReactProvider<any> = (frame.type: any);
824+
this.popProvider(provider);
825+
}
826+
continue;
813827
}
814-
continue;
815-
}
816-
const child = frame.children[frame.childIndex++];
817-
if (__DEV__) {
818-
pushCurrentDebugStack(this.stack);
819-
// We're starting work on this frame, so reset its inner stack.
820-
((frame: any): FrameDev).debugElementStack.length = 0;
821-
try {
822-
// Be careful! Make sure this matches the PROD path below.
828+
const child = frame.children[frame.childIndex++];
829+
if (__DEV__) {
830+
pushCurrentDebugStack(this.stack);
831+
// We're starting work on this frame, so reset its inner stack.
832+
((frame: any): FrameDev).debugElementStack.length = 0;
833+
try {
834+
// Be careful! Make sure this matches the PROD path below.
835+
out += this.render(child, frame.context, frame.domNamespace);
836+
} finally {
837+
popCurrentDebugStack();
838+
}
839+
} else {
840+
// Be careful! Make sure this matches the DEV path above.
823841
out += this.render(child, frame.context, frame.domNamespace);
824-
} finally {
825-
popCurrentDebugStack();
826842
}
827-
} else {
828-
// Be careful! Make sure this matches the DEV path above.
829-
out += this.render(child, frame.context, frame.domNamespace);
830843
}
844+
return out;
845+
} finally {
846+
ReactCurrentOwner.currentDispatcher = null;
831847
}
832-
return out;
833848
}
834849

835850
render(

0 commit comments

Comments
 (0)