Skip to content

Commit f5aaf4c

Browse files
committed
Moved home page example code to /content/home
Now examples are trasnformed to GraphQL during build and assembled by the index template. This makes them easier to edit and tie in with their associated markdown description.
1 parent 65f1ced commit f5aaf4c

13 files changed

+237
-192
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
class MarkdownEditor extends React.Component {
2+
constructor(props) {
3+
super(props);
4+
this.handleChange = this.handleChange.bind(this);
5+
this.state = { value: 'Type some *markdown* here!' };
6+
}
7+
8+
handleChange(e) {
9+
this.setState({ value: e.target.value });
10+
}
11+
12+
getRawMarkup() {
13+
const md = new Remarkable();
14+
return { __html: md.render(this.state.value) };
15+
}
16+
17+
render() {
18+
return (
19+
<div className="MarkdownEditor">
20+
<h3>Input</h3>
21+
<textarea
22+
onChange={this.handleChange}
23+
defaultValue={this.state.value}
24+
/>
25+
<h3>Output</h3>
26+
<div
27+
className="content"
28+
dangerouslySetInnerHTML={this.getRawMarkup()}
29+
/>
30+
</div>
31+
);
32+
}
33+
}
34+
35+
ReactDOM.render(<MarkdownEditor />, mountNode);
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
---
22
title: A Component Using External Plugins
33
order: 3
4-
example_name: markdownExample
54
---
65

76
React is flexible and provides hooks that allow you to interface with other libraries and frameworks. This example uses **remarkable**, an external Markdown library, to convert the `<textarea>`'s value in real time.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
class HelloMessage extends React.Component {
2+
render() {
3+
return (
4+
<div>
5+
Hello {this.props.name}
6+
</div>
7+
);
8+
}
9+
}
10+
11+
ReactDOM.render(
12+
<HelloMessage name="Taylor" />,
13+
mountNode
14+
);
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
---
22
title: A Simple Component
33
order: 0
4-
example_name: helloExample
54
---
65

76
React components implement a `render()` method that takes input data and returns what to display. This example uses an XML-like syntax called JSX. Input data that is passed into the component can be accessed by `render()` via `this.props`.
87

9-
**JSX is optional and not required to use React.** Try the [Babel REPL](http://babeljs.io/repl#?babili=false&browsers=&build=&builtIns=false&code_lz=MYGwhgzhAEASCmIQHsCy8pgOb2vAHgC7wB2AJjAErxjCEB0AwsgLYAOyJph0A3gFABIAE6ky8YQAoAlHyEj4hAK7CS0ADxkAlgDcAfAiTI-hABZaI9NsORtLJMC3gBfdQHpt-gNxDn_P_zUtIQAIgDyqPSi5BKS6oYo6Jg40A5OALwARCHwOlokmdBuegA00CzISiSEAHLI4tJeQA&debug=false&circleciRepo=&evaluate=false&lineWrap=false&presets=react&prettier=true&targets=&version=6.26.0) to see the raw JavaScript code produced by the JSX compilation step.
8+
**JSX is optional and not required to use React.** Try the [Babel REPL](http://babeljs.io/repl#?babili=false&browsers=&build=&builtIns=false&code_lz=MYGwhgzhAEASCmIQHsCy8pgOb2vAHgC7wB2AJjAErxjCEB0AwsgLYAOyJph0A3gFDRoAJ1Jl4wgBQBKPoKEj4hAK7CS0SfIXQAPGQCWANwB8W7XEQo-hABb6I9NsORsHJMC3gBfM0J0B6AxMzaQBueR8ffmpaQgARAHlUelFyCU0_BCQ0DAhsXHdPAF4AIgAVMABPFGES6H9jABp5FmRlEkIAOWRxfjCgA&debug=false&circleciRepo=&evaluate=false&lineWrap=false&presets=react&targets=&version=6.26.0) to see the raw JavaScript code produced by the JSX compilation step.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
class Timer extends React.Component {
2+
constructor(props) {
3+
super(props);
4+
this.state = { seconds: 0 };
5+
}
6+
7+
tick() {
8+
this.setState(prevState => ({
9+
seconds: prevState.seconds + 1
10+
}));
11+
}
12+
13+
componentDidMount() {
14+
this.interval = setInterval(() => this.tick(), 1000);
15+
}
16+
17+
componentWillUnmount() {
18+
clearInterval(this.interval);
19+
}
20+
21+
render() {
22+
return (
23+
<div>
24+
Seconds: {this.state.seconds}
25+
</div>
26+
);
27+
}
28+
}
29+
30+
ReactDOM.render(<Timer />, mountNode);
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
---
22
title: A Stateful Component
33
order: 1
4-
example_name: timerExample
54
---
65

76
In addition to taking input data (accessed via `this.props`), a component can maintain internal state data (accessed via `this.state`). When a component's state data changes, the rendered markup will be updated by re-invoking `render()`.
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
class TodoApp extends React.Component {
2+
constructor(props) {
3+
super(props);
4+
this.state = { items: [], text: '' };
5+
this.handleChange = this.handleChange.bind(this);
6+
this.handleSubmit = this.handleSubmit.bind(this);
7+
}
8+
9+
render() {
10+
return (
11+
<div>
12+
<h3>TODO</h3>
13+
<TodoList items={this.state.items} />
14+
<form onSubmit={this.handleSubmit}>
15+
<input
16+
onChange={this.handleChange}
17+
value={this.state.text}
18+
/>
19+
<button>
20+
Add #{this.state.items.length + 1}
21+
</button>
22+
</form>
23+
</div>
24+
);
25+
}
26+
27+
handleChange(e) {
28+
this.setState({ text: e.target.value });
29+
}
30+
31+
handleSubmit(e) {
32+
e.preventDefault();
33+
if (!this.state.text.length) {
34+
return;
35+
}
36+
const newItem = {
37+
text: this.state.text,
38+
id: Date.now()
39+
};
40+
this.setState(prevState => ({
41+
items: prevState.items.concat(newItem),
42+
text: ''
43+
}));
44+
}
45+
}
46+
47+
class TodoList extends React.Component {
48+
render() {
49+
return (
50+
<ul>
51+
{this.props.items.map(item => (
52+
<li key={item.id}>{item.text}</li>
53+
))}
54+
</ul>
55+
);
56+
}
57+
}
58+
59+
ReactDOM.render(<TodoApp />, mountNode);
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
---
22
title: An Application
33
order: 2
4-
example_name: todoExample
54
---
65

76
Using `props` and `state`, we can put together a small Todo application. This example uses `state` to track the current list of items as well as the text that the user has entered. Although event handlers appear to be rendered inline, they will be collected and implemented using event delegation.

gatsby-config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ module.exports = {
1919
plugins: [
2020
'gatsby-source-react-error-codes',
2121
'gatsby-transformer-authors-yaml',
22+
'gatsby-transformer-home-example-code',
2223
'gatsby-plugin-netlify',
2324
'gatsby-plugin-glamor',
2425
'gatsby-plugin-react-next',

gatsby-node.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ exports.onCreateNode = ({node, boundActionCreators, getNode}) => {
208208
if (!slug) {
209209
slug = `/${relativePath.replace('.md', '.html')}`;
210210

211-
// This should (probably) only happen for the index.md,
211+
// This should only happen for the partials in /content/home,
212212
// But let's log it in case it happens for other files also.
213213
console.warn(
214214
`Warning: No slug found for "${relativePath}". Falling back to default "${slug}".`,
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
const {readdirSync, readFileSync} = require('fs');
2+
const {join, resolve} = require('path');
3+
4+
// Store code snippets in GraphQL for the home page examples.
5+
// Snippets will be matched with markdown templates of the same name.
6+
exports.sourceNodes = ({graphql, boundActionCreators}) => {
7+
const {createNode} = boundActionCreators;
8+
9+
const path = resolve(__dirname, '../../content/home/examples');
10+
const files = readdirSync(path);
11+
12+
files.forEach(file => {
13+
if (file.match(/\.js$/)) {
14+
const code = readFileSync(join(path, file), 'utf8');
15+
const id = file.replace(/\.js$/, '');
16+
17+
createNode({
18+
id,
19+
children: [],
20+
parent: 'EXAMPLES',
21+
internal: {
22+
type: 'ExampleCode',
23+
contentDigest: JSON.stringify(code),
24+
},
25+
});
26+
}
27+
});
28+
};
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"name": "gatsby-transformer-home-example-code",
3+
"version": "0.0.1"
4+
}

0 commit comments

Comments
 (0)