Skip to content

Commit f66ed55

Browse files
author
Sunil Pai
committed
Merge remote-tracking branch 'upstream/master' into async-act
2 parents 3766812 + 52c870c commit f66ed55

File tree

66 files changed

+2325
-1127
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+2325
-1127
lines changed

fixtures/dom/public/renderer.js

Lines changed: 79 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,30 @@
1313
var renders = 0;
1414
var failed = false;
1515

16+
var needsReactDOM = getBooleanQueryParam('needsReactDOM');
17+
var needsCreateElement = getBooleanQueryParam('needsCreateElement');
18+
19+
function unmountComponent(node) {
20+
// ReactDOM was moved into a separate package in 0.14
21+
if (needsReactDOM) {
22+
ReactDOM.unmountComponentAtNode(node);
23+
} else if (React.unmountComponentAtNode) {
24+
React.unmountComponentAtNode(node);
25+
} else {
26+
// Unmounting for React 0.4 and lower
27+
React.unmountAndReleaseReactRootNode(node);
28+
}
29+
}
30+
31+
function createElement(value) {
32+
// React.createElement replaced function invocation in 0.12
33+
if (needsCreateElement) {
34+
return React.createElement(value);
35+
} else {
36+
return value();
37+
}
38+
}
39+
1640
function getQueryParam(key) {
1741
var pattern = new RegExp(key + '=([^&]+)(&|$)');
1842
var matches = window.location.search.match(pattern);
@@ -35,20 +59,56 @@
3559
function prerender() {
3660
setStatus('Generating markup');
3761

38-
output.innerHTML = ReactDOMServer.renderToString(
39-
React.createElement(Fixture)
40-
);
62+
return Promise.resolve()
63+
.then(function() {
64+
const element = createElement(Fixture);
65+
66+
// Server rendering moved to a separate package along with ReactDOM
67+
// in 0.14.0
68+
if (needsReactDOM) {
69+
return ReactDOMServer.renderToString(element);
70+
}
71+
72+
// React.renderComponentToString was renamed in 0.12
73+
if (React.renderToString) {
74+
return React.renderToString(element);
75+
}
4176

42-
setStatus('Markup only (No React)');
77+
// React.renderComponentToString became synchronous in React 0.9.0
78+
if (React.renderComponentToString.length === 1) {
79+
return React.renderComponentToString(element);
80+
}
81+
82+
// Finally, React 0.4 and lower emits markup in a callback
83+
return new Promise(function(resolve) {
84+
React.renderComponentToString(element, resolve);
85+
});
86+
})
87+
.then(function(string) {
88+
output.innerHTML = string;
89+
setStatus('Markup only (No React)');
90+
})
91+
.catch(handleError);
4392
}
4493

4594
function render() {
4695
setStatus('Hydrating');
4796

48-
if (ReactDOM.hydrate) {
49-
ReactDOM.hydrate(React.createElement(Fixture), output);
97+
var element = createElement(Fixture);
98+
99+
// ReactDOM was split out into another package in 0.14
100+
if (needsReactDOM) {
101+
// Hydration changed to a separate method in React 16
102+
if (ReactDOM.hydrate) {
103+
ReactDOM.hydrate(element, output);
104+
} else {
105+
ReactDOM.render(element, output);
106+
}
107+
} else if (React.render) {
108+
// React.renderComponent was renamed in 0.12
109+
React.render(element, output);
50110
} else {
51-
ReactDOM.render(React.createElement(Fixture), output);
111+
React.renderComponent(element, output);
52112
}
53113

54114
setStatus(renders > 0 ? 'Re-rendered (' + renders + 'x)' : 'Hydrated');
@@ -85,17 +145,17 @@
85145
setStatus('Failed');
86146
output.innerHTML = 'Please name your root component "Fixture"';
87147
} else {
88-
prerender();
89-
90-
if (getBooleanQueryParam('hydrate')) {
91-
render();
92-
}
148+
prerender().then(function() {
149+
if (getBooleanQueryParam('hydrate')) {
150+
render();
151+
}
152+
});
93153
}
94154
}
95155

96156
function reloadFixture(code) {
97157
renders = 0;
98-
ReactDOM.unmountComponentAtNode(output);
158+
unmountComponent(output);
99159
injectFixture(code);
100160
}
101161

@@ -109,12 +169,12 @@
109169

110170
loadScript(getQueryParam('reactPath'))
111171
.then(function() {
112-
return getBooleanQueryParam('needsReactDOM')
113-
? loadScript(getQueryParam('reactDOMPath'))
114-
: null;
115-
})
116-
.then(function() {
117-
return loadScript(getQueryParam('reactDOMServerPath'));
172+
if (needsReactDOM) {
173+
return Promise.all([
174+
loadScript(getQueryParam('reactDOMPath')),
175+
loadScript(getQueryParam('reactDOMServerPath')),
176+
]);
177+
}
118178
})
119179
.then(function() {
120180
if (failed) {

fixtures/dom/src/components/App.js

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@ import '../style.css';
44

55
const React = window.React;
66

7-
function App() {
8-
return (
9-
<div>
10-
<Header />
11-
<Fixtures />
12-
</div>
13-
);
7+
class App extends React.Component {
8+
render() {
9+
return (
10+
<div>
11+
<Header />
12+
<Fixtures />
13+
</div>
14+
);
15+
}
1416
}
1517

1618
export default App;

fixtures/dom/src/components/Header.js

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import {parse, stringify} from 'query-string';
2-
import getVersionTags from '../tags';
2+
import VersionPicker from './VersionPicker';
3+
34
const React = window.React;
45

56
class Header extends React.Component {
@@ -9,18 +10,12 @@ class Header extends React.Component {
910
const version = query.version || 'local';
1011
const production = query.production || false;
1112
const versions = [version];
13+
1214
this.state = {version, versions, production};
1315
}
14-
componentWillMount() {
15-
getVersionTags().then(tags => {
16-
let versions = tags.map(tag => tag.name.slice(1));
17-
versions = [`local`, ...versions];
18-
this.setState({versions});
19-
});
20-
}
21-
handleVersionChange(event) {
16+
handleVersionChange(version) {
2217
const query = parse(window.location.search);
23-
query.version = event.target.value;
18+
query.version = version;
2419
if (query.version === 'local') {
2520
delete query.version;
2621
}
@@ -48,7 +43,10 @@ class Header extends React.Component {
4843
width="20"
4944
height="20"
5045
/>
51-
<a href="/">DOM Test Fixtures (v{React.version})</a>
46+
<a href="/">
47+
DOM Test Fixtures (v
48+
{React.version})
49+
</a>
5250
</span>
5351

5452
<div className="header-controls">
@@ -90,17 +88,14 @@ class Header extends React.Component {
9088
<option value="/suspense">Suspense</option>
9189
</select>
9290
</label>
93-
<label htmlFor="react_version">
91+
<label htmlFor="global_version">
9492
<span className="sr-only">Select a version to test</span>
95-
<select
96-
value={this.state.version}
97-
onChange={this.handleVersionChange}>
98-
{this.state.versions.map(version => (
99-
<option key={version} value={version}>
100-
{version}
101-
</option>
102-
))}
103-
</select>
93+
<VersionPicker
94+
id="global_version"
95+
name="global_version"
96+
version={this.state.version}
97+
onChange={this.handleVersionChange}
98+
/>
10499
</label>
105100
</div>
106101
</div>
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import getVersionTags from '../tags';
2+
3+
const React = window.React;
4+
5+
class VersionPicker extends React.Component {
6+
constructor(props, context) {
7+
super(props, context);
8+
const version = props.version || 'local';
9+
const versions = [version];
10+
this.state = {versions};
11+
}
12+
13+
componentWillMount() {
14+
getVersionTags().then(tags => {
15+
let versions = tags.map(tag => tag.name.slice(1));
16+
versions = [`local`, ...versions];
17+
this.setState({versions});
18+
});
19+
}
20+
21+
onChange = event => {
22+
this.props.onChange(event.target.value);
23+
};
24+
25+
render() {
26+
const {version, id, name} = this.props;
27+
const {versions} = this.state;
28+
29+
return (
30+
<select id={id} name={name} value={version} onChange={this.onChange}>
31+
{versions.map(version => (
32+
<option key={version} value={version}>
33+
{version}
34+
</option>
35+
))}
36+
</select>
37+
);
38+
}
39+
}
40+
41+
export default VersionPicker;

fixtures/dom/src/components/fixtures/hydration/Code.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import {findDOMNode} from '../../../find-dom-node';
2+
13
const React = window.React;
24

35
export class CodeEditor extends React.Component {
@@ -6,6 +8,8 @@ export class CodeEditor extends React.Component {
68
}
79

810
componentDidMount() {
11+
this.textarea = findDOMNode(this);
12+
913
// Important: CodeMirror incorrectly lays out the editor
1014
// if it executes before CSS has loaded
1115
// https://github.com/graphql/graphiql/issues/33#issuecomment-318188555
@@ -44,7 +48,6 @@ export class CodeEditor extends React.Component {
4448
render() {
4549
return (
4650
<textarea
47-
ref={ref => (this.textarea = ref)}
4851
defaultValue={this.props.code}
4952
autoComplete="off"
5053
hidden={true}
@@ -72,6 +75,10 @@ export class CodeError extends React.Component {
7275
if (supportsDetails) {
7376
const [summary, ...body] = error.message.split(/\n+/g);
7477

78+
if (body.length >= 0) {
79+
return <div className={className}>{summary}</div>;
80+
}
81+
7582
return (
7683
<details className={className}>
7784
<summary>{summary}</summary>

fixtures/dom/src/components/fixtures/hydration/hydration.css

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
.hydration-options label {
2424
font-size: 13px;
25+
margin-right: 10px;
2526
}
2627

2728
.hydration-options input[type=checkbox] {
@@ -30,6 +31,11 @@
3031
vertical-align: middle;
3132
}
3233

34+
.hydration-options select {
35+
margin-left: 10px;
36+
max-width: 100px;
37+
}
38+
3339
.hydration .CodeMirror {
3440
font-size: 13px;
3541
padding-top: 8px;

fixtures/dom/src/components/fixtures/hydration/index.js

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,23 @@
11
import './hydration.css';
2+
import VersionPicker from '../../VersionPicker';
23
import {SAMPLE_CODE} from './data';
34
import {CodeEditor, CodeError} from './Code';
45
import {compile} from './code-transformer';
56
import {reactPaths} from '../../../react-loader';
67
import qs from 'query-string';
78

89
const React = window.React;
10+
// The Hydration fixture can render at a different version than the parent
11+
// app. This allows rendering for versions of React older than the DOM
12+
// test fixtures can support.
13+
const initialVersion = qs.parse(window.location.search).version || 'local';
914

1015
class Hydration extends React.Component {
1116
state = {
1217
error: null,
1318
code: SAMPLE_CODE,
1419
hydrate: true,
20+
version: initialVersion,
1521
};
1622

1723
ready = false;
@@ -72,9 +78,14 @@ class Hydration extends React.Component {
7278
});
7379
};
7480

81+
setVersion = version => {
82+
this.setState({version});
83+
};
84+
7585
render() {
76-
const {code, error, hydrate} = this.state;
77-
const src = '/renderer.html?' + qs.stringify({hydrate, ...reactPaths()});
86+
const {code, error, hydrate, version} = this.state;
87+
const src =
88+
'/renderer.html?' + qs.stringify({hydrate, ...reactPaths(version)});
7889

7990
return (
8091
<div className="hydration">
@@ -89,6 +100,16 @@ class Hydration extends React.Component {
89100
/>
90101
Auto-Hydrate
91102
</label>
103+
104+
<label htmlFor="hydration_version">
105+
Version:
106+
<VersionPicker
107+
id="hydration_version"
108+
name="hyration_version"
109+
version={version}
110+
onChange={this.setVersion}
111+
/>
112+
</label>
92113
</header>
93114

94115
<CodeEditor code={code} onChange={this.setCode} />

0 commit comments

Comments
 (0)