Skip to content
This repository was archived by the owner on Feb 21, 2022. It is now read-only.

Commit 17517b9

Browse files
committed
Refactor ExampleBrowser
- navigate between examples with react-router (each example has got a slug) - extract ExampleViewer into a separate component, determine its size using react-sizeme - make ExampleBrowser component functional (i.e. pure)
1 parent 281ec03 commit 17517b9

5 files changed

Lines changed: 77 additions & 82 deletions

File tree

assets/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161

6262
#panel #content .link {
6363
color: #2194CE;
64+
display: block;
6465
text-decoration: none;
6566
cursor: pointer;
6667
}

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
"cannon": "^0.6.2",
2121
"react": "~15.3.1",
2222
"react-dom": "^15.3.1",
23+
"react-router": "^3.0.0-alpha.3",
24+
"react-sizeme": "^2.1.3",
2325
"react-three-renderer": "2.3.1",
2426
"stats.js": "^1.0.0",
2527
"three": "0.79.0"

src/examples/ExampleBrowser.js

Lines changed: 30 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import React from 'react';
2+
import { Link } from 'react-router';
3+
import ExampleViewer from './ExampleViewer';
24

35
import SimpleExample from './Simple/index';
46
import ManualRenderingExample from './ManualRendering/index';
@@ -17,41 +19,49 @@ const examples = [
1719
name: 'Simple',
1820
component: SimpleExample,
1921
url: 'Simple/index',
22+
slug: 'webgl_simple',
2023
},
2124
{
2225
name: 'Cloth',
2326
component: ClothExample,
2427
url: 'AnimationCloth/index',
28+
slug: 'webgl_cloth',
2529
},
2630
{
2731
name: 'Camera',
2832
component: CameraExample,
2933
url: 'WebGLCameraExample/index',
34+
slug: 'webgl_camera',
3035
},
3136
{
3237
name: 'Geometries',
3338
component: GeometriesExample,
3439
url: 'Geometries/index',
40+
slug: 'webgl_geometries',
3541
},
3642
{
3743
name: 'Geometry Shapes',
3844
component: GeometryShapesExample,
3945
url: 'GeometryShapes/index',
46+
slug: 'webgl_geometry_shapes',
4047
},
4148
{
4249
name: 'Draggable Cubes',
4350
component: DraggableCubes,
4451
url: 'DraggableCubes/index',
52+
slug: 'webgl_draggable_cubes',
4553
},
4654
{
4755
name: 'Physics',
4856
component: Physics,
4957
url: 'Physics/index',
58+
slug: 'webgl_physics',
5059
},
5160
{
5261
name: 'Physics - MousePick',
5362
component: PhysicsMousePick,
5463
url: 'Physics/mousePick',
64+
slug: 'webgl_physics_mousepick',
5565
},
5666
{
5767
separator: true,
@@ -66,6 +76,7 @@ const examples = [
6676
name: 'Manual rendering',
6777
component: ManualRenderingExample,
6878
url: 'ManualRendering/index',
79+
slug: 'advanced_manual_rendering',
6980
},
7081
{
7182
separator: true,
@@ -75,74 +86,20 @@ const examples = [
7586
name: 'RotatingCubes - Through React',
7687
component: BenchmarkRotatingCubes,
7788
url: 'Benchmark/RotatingCubes',
89+
slug: 'benchmarks_rotating_cubes_react',
7890
},
7991
{
8092
name: 'RotatingCubes - Direct Updates',
8193
component: RotatingCubesDirectUpdates,
8294
url: 'Benchmark/RotatingCubesDirectUpdates',
95+
slug: 'benchmarks_rotating_cubes_direct',
8396
},
8497
];
8598

86-
class ExampleBrowser extends React.Component {
87-
constructor(props, context) {
88-
super(props, context);
89-
90-
this.state = {
91-
activeExample: null,
92-
viewerWidth: 0,
93-
viewerHeight: 0,
94-
};
95-
}
96-
97-
componentDidMount() {
98-
window.addEventListener('resize', this._onWindowResize, false);
99-
}
100-
101-
componentWillUnmount() {
102-
window.removeEventListener('resize', this._onWindowResize, false);
103-
}
104-
105-
_onWindowResize = () => {
106-
const viewer = this.refs.viewer;
107-
108-
this.setState({
109-
viewerWidth: viewer.offsetWidth,
110-
viewerHeight: viewer.offsetHeight,
111-
});
112-
};
113-
114-
render() {
115-
let exampleContent = null;
116-
117-
const {
118-
viewerWidth,
119-
viewerHeight,
120-
} = this.state;
121-
122-
let sourceButton = null;
123-
124-
if (this.state.activeExample !== null) {
125-
const {
126-
component: ExampleComponent,
127-
url,
128-
} = examples[this.state.activeExample];
129-
130-
exampleContent = (<ExampleComponent
131-
width={viewerWidth}
132-
height={viewerHeight}
133-
/>);
134-
135-
sourceButton = (<div key="src" id="button">
136-
<a
137-
href={`https://github.com/toxicFork/react-three-renderer-example/blob/master/src/examples/${url}.js`}
138-
target="_blank"
139-
>
140-
View source
141-
</a>
142-
</div>);
143-
}
144-
145-
return (<div>
99+
const ExampleBrowser = ({ params }) => {
100+
const activeExample = params.slug && examples.find(example => example.slug === params.slug);
101+
return (
102+
<div>
146103
<div id="panel" className="collapsed">
147104
<h1><a href="https://github.com/toxicFork/react-three-renderer/">react-three-renderer</a> / examples</h1>
148105
<div id="content">
@@ -159,33 +116,25 @@ class ExampleBrowser extends React.Component {
159116
</div>);
160117
}
161118

162-
const onLinkClick = () => {
163-
const viewer = this.refs.viewer;
164-
165-
this.setState({
166-
viewerWidth: viewer.offsetWidth,
167-
viewerHeight: viewer.offsetHeight,
168-
activeExample: index,
169-
});
170-
};
171-
172-
return (<div
173-
className="link"
119+
return (<Link
120+
to={`/${example.slug}`}
174121
key={index}
175-
onClick={onLinkClick}
122+
className="link"
123+
activeClassName="selected"
176124
>
177125
{example.name}
178-
</div>);
126+
</Link>);
179127
})}
180128
</div>
181129
</div>
182130
</div>
183-
<div id="viewer" ref="viewer">
184-
{exampleContent}
185-
{sourceButton}
186-
</div>
187-
</div>);
188-
}
189-
}
131+
<ExampleViewer example={activeExample} />
132+
</div>
133+
);
134+
};
135+
136+
ExampleBrowser.propTypes = {
137+
params: React.PropTypes.object.isRequired,
138+
};
190139

191140
export default ExampleBrowser;

src/examples/ExampleViewer.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import React from 'react';
2+
import sizeMe from 'react-sizeme';
3+
4+
const ExampleViewer = ({ example, size }) => {
5+
let sourceButton = null;
6+
let exampleContent = null;
7+
8+
if (example) {
9+
const {
10+
component: ExampleComponent,
11+
url,
12+
} = example;
13+
exampleContent = (<ExampleComponent width={size.width} height={size.height} />);
14+
sourceButton = (<div key="src" id="button">
15+
<a
16+
href={`https://github.com/toxicFork/react-three-renderer-example/blob/master/src/examples/${url}.js`}
17+
target="_blank"
18+
>
19+
View source
20+
</a>
21+
</div>);
22+
}
23+
24+
return (
25+
<div id="viewer">
26+
{exampleContent}
27+
{sourceButton}
28+
</div>
29+
);
30+
};
31+
32+
ExampleViewer.propTypes = {
33+
example: React.PropTypes.object,
34+
size: React.PropTypes.object,
35+
};
36+
37+
export default sizeMe({ monitorHeight: true, refreshRate: 200 })(ExampleViewer);

src/index.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
11
import React from 'react';
22
import ReactDOM from 'react-dom';
3+
import { Router, Route, hashHistory } from 'react-router';
34
import ExampleBrowser from './examples/ExampleBrowser';
45
import Perf from 'react-addons-perf';
56

67
window.Perf = Perf;
78

8-
ReactDOM.render(<ExampleBrowser/>, document.getElementById('content'));
9+
ReactDOM.render(
10+
<Router history={hashHistory}>
11+
<Route path="/(:slug)" component={ExampleBrowser} />
12+
</Router>,
13+
document.getElementById('content')
14+
);

0 commit comments

Comments
 (0)