Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Home page examples hooks and classes #2838

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
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
3 changes: 1 addition & 2 deletions .flowconfig
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ module.system.node.resolve_dirname=src

esproposal.class_static_fields=enable
esproposal.class_instance_fields=enable
unsafe.enable_getters_and_setters=true

munge_underscores=false

Expand All @@ -32,4 +31,4 @@ suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError

[version]
^0.56.0
^0.120.1
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
title: A Component Using External Plugins
order: 3
domid: markdown-example
hooks: false
---

React allows 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.
1 change: 1 addition & 0 deletions content/home/examples/a-simple-component.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
title: A Simple Component
order: 0
domid: hello-example
hooks: false
---

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`.
Expand Down
1 change: 1 addition & 0 deletions content/home/examples/a-stateful-component.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
title: A Stateful Component
order: 1
domid: timer-example
hooks: false
---

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()`.
1 change: 1 addition & 0 deletions content/home/examples/an-application.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
title: An Application
order: 2
domid: todos-example
hooks: false
---

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.
31 changes: 31 additions & 0 deletions content/home/examples/hooks-a-component-using-external-plugins.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
const MarkdownEditor = () => {
const [value, setValue] = React.useState('Hello, **world**!');

const handleChange = e => {
setValue(e.target.value);
};

const getRawMarkup = () => {
const md = new Remarkable();
return {__html: md.render(value)};
};

return (
<div className="MarkdownEditor">
<h3>Input</h3>
<label htmlFor="markdown-content">Enter some markdown</label>
<textarea
id="markdown-content"
onChange={handleChange}
defaultValue={value}
/>
<h3>Output</h3>
<div className="content" dangerouslySetInnerHTML={getRawMarkup()} />
</div>
);
};

ReactDOM.render(
<MarkdownEditor />,
document.getElementById('markdown-example'),
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
title: A Component Using External Plugins
order: 3
domid: markdown-example
hooks: true
---

React allows 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.
8 changes: 8 additions & 0 deletions content/home/examples/hooks-a-simple-component.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
const HelloMessage = props => {
return <div>Hello {props.name}</div>;
};

ReactDOM.render(
<HelloMessage name="Taylor" />,
document.getElementById('hello-example'),
);
10 changes: 10 additions & 0 deletions content/home/examples/hooks-a-simple-component.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
title: A Simple Component
order: 0
domid: hello-example
hooks: true
---

React function components return what to display. This example uses an XML-like syntax called JSX. Input data that is passed into the component can be accessed as function arguments (`props` in this example)

**JSX is optional and not required to use React.** Try the [Babel REPL](babel://es5-syntax-example) to see the raw JavaScript code produced by the JSX compilation step.
17 changes: 17 additions & 0 deletions content/home/examples/hooks-a-stateful-component.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
const Timer = () => {
const [seconds, setSeconds] = React.useState(0);

const tick = () => {
setSeconds(sec => sec + 1);
};

React.useEffect(() => {
const interval = setInterval(tick, 1000);

return () => clearInterval(interval);
}, []);

return <div>Seconds: {seconds}</div>;
};

ReactDOM.render(<Timer />, document.getElementById('timer-example'));
8 changes: 8 additions & 0 deletions content/home/examples/hooks-a-stateful-component.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
title: A Stateful Component
order: 1
domid: timer-example
hooks: true
---

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()`.
45 changes: 45 additions & 0 deletions content/home/examples/hooks-an-application.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
const TodoApp = () => {
const [items, setItems] = React.useState([]);
const [text, setText] = React.useState('');

const handleSubmit = e => {
e.preventDefault();
if (text.length === 0) {
return;
}
const newItem = {
text,
id: Date.now(),
};
setItems(items.concat(newItem));
setText('');
};

const handleChange = e => {
setText(e.target.value);
};

return (
<div>
<h3>TODO</h3>
<TodoList items={items} />
<form onSubmit={handleSubmit}>
<label htmlFor="new-todo">What needs to be done?</label>
<input id="new-todo" onChange={handleChange} value={text} />
<button>Add #{items.length + 1}</button>
</form>
</div>
);
};

const TodoList = props => {
return (
<ul>
{props.items.map(item => (
<li key={item.id}>{item.text}</li>
))}
</ul>
);
};

ReactDOM.render(<TodoApp />, document.getElementById('todos-example'));
8 changes: 8 additions & 0 deletions content/home/examples/hooks-an-application.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
title: An Application
order: 2
domid: todos-example
hooks: true
---

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.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"eslint-plugin-prettier": "^2.3.1",
"eslint-plugin-react": "^7.4.0",
"eslint-plugin-relay": "^0.0.19",
"flow-bin": "^0.56.0",
"flow-bin": "^0.120.1",
"gatsby": "^2.0.0",
"gatsby-plugin-catch-links": "^2.0.0",
"gatsby-plugin-feed": "^2.0.0",
Expand Down
86 changes: 72 additions & 14 deletions src/pages/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import logoWhiteSvg from 'icons/logo-white.svg';
class Home extends Component {
state = {
babelLoaded: false,
hooks: true,
};

componentDidMount() {
Expand All @@ -37,15 +38,33 @@ class Home extends Component {
);
}

useHooks = () => {
this.setState({hooks: true});
};

useClasses = () => {
this.setState({hooks: false});
};

render() {
const {babelLoaded} = this.state;
const {babelLoaded, hooks} = this.state;
const {data, location} = this.props;
const {codeExamples, examples, marketing} = data;

const code = codeExamples.edges.reduce((lookup, {node}) => {
lookup[node.mdAbsolutePath] = node;
return lookup;
}, {});
const computedExamples = examples.edges.filter(
({node}) => node.frontmatter.hooks === hooks,
);

const code = codeExamples.edges
.filter(({node}) =>
computedExamples.find(
example => example.node.fileAbsolutePath === node.mdAbsolutePath,
),
)
.reduce((lookup, {node}) => {
lookup[node.mdAbsolutePath] = node;
return lookup;
}, {});

return (
<Layout location={location}>
Expand Down Expand Up @@ -248,17 +267,37 @@ class Home extends Component {
))}
</div>
</section>
<hr
css={{
height: 1,
marginBottom: -1,
border: 'none',
borderBottom: `1 solid ${colors.divider}`,
}}
/>

<div css={{display: 'flex', marginBottom: '20px'}}>
<button
css={[
examplesTabStyles,
{
...(hooks
? examplesTabSelectedStyles
: examplesTabNotSelectedStyles),
},
]}
onClick={this.useHooks}>
Hooks
</button>
<button
css={[
examplesTabStyles,
{
...(hooks
? examplesTabNotSelectedStyles
: examplesTabSelectedStyles),
},
]}
onClick={this.useClasses}>
Classes
</button>
</div>

<section css={sectionStyles}>
<div id="examples">
{examples.edges.map(({node}, index) => {
{computedExamples.map(({node}, index) => {
const snippet = code[node.fileAbsolutePath];
return (
<CodeExample
Expand Down Expand Up @@ -378,6 +417,7 @@ export const pageQuery = graphql`
frontmatter {
title
domid
hooks
}
html
}
Expand Down Expand Up @@ -416,3 +456,21 @@ const headingStyles = {
marginBottom: 20,
},
};

const examplesTabStyles = {
width: '100%',
textAlign: 'center',
padding: '12px',
cursor: 'pointer',
border: '1px solid #ececec',
outline: 'none',
};

const examplesTabSelectedStyles = {
borderBottomColor: '#ffffff',
};
const examplesTabNotSelectedStyles = {
borderTopColor: '#ffffff',
borderLeftColor: '#ffffff',
borderRightColor: '#ffffff',
};
Loading