diff --git a/content/docs/handling-events.md b/content/docs/handling-events.md
index 175303c24ef..4d7e0688e91 100644
--- a/content/docs/handling-events.md
+++ b/content/docs/handling-events.md
@@ -39,20 +39,7 @@ Another difference is that you cannot return `false` to prevent default behavior
In React, this could instead be:
-```js{2-5,8}
-function ActionLink() {
- function handleClick(e) {
- e.preventDefault();
- console.log('The link was clicked.');
- }
-
- return (
-
- Click me
-
- );
-}
-```
+`embed:handling-events/action-link-example.js`
Here, `e` is a synthetic event. React defines these synthetic events according to the [W3C spec](https://www.w3.org/TR/DOM-Level-3-Events/), so you don't need to worry about cross-browser compatibility. See the [`SyntheticEvent`](/docs/events.html) reference guide to learn more.
@@ -60,38 +47,9 @@ When using React you should generally not need to call `addEventListener` to add
When you define a component using an [ES6 class](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Classes), a common pattern is for an event handler to be a method on the class. For example, this `Toggle` component renders a button that lets the user toggle between "ON" and "OFF" states:
-```js{6,7,10-14,18}
-class Toggle extends React.Component {
- constructor(props) {
- super(props);
- this.state = {isToggleOn: true};
-
- // This binding is necessary to make `this` work in the callback
- this.handleClick = this.handleClick.bind(this);
- }
-
- handleClick() {
- this.setState(state => ({
- isToggleOn: !state.isToggleOn
- }));
- }
-
- render() {
- return (
-
- );
- }
-}
-
-ReactDOM.render(
- ,
- document.getElementById('root')
-);
-```
+`embed:handling-events/toggle-example.js`
-[**Try it on CodePen**](https://codepen.io/gaearon/pen/xEmzGg?editors=0010)
+**[Try it on CodeSandbox](codesandbox://handling-events/toggle-example,handling-events/toggle-example.css)**
You have to be careful about the meaning of `this` in JSX callbacks. In JavaScript, class methods are not [bound](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_objects/Function/bind) by default. If you forget to bind `this.handleClick` and pass it to `onClick`, `this` will be `undefined` when the function is actually called.
@@ -99,44 +57,13 @@ This is not React-specific behavior; it is a part of [how functions work in Java
If calling `bind` annoys you, there are two ways you can get around this. If you are using the experimental [public class fields syntax](https://babeljs.io/docs/plugins/transform-class-properties/), you can use class fields to correctly bind callbacks:
-```js{2-6}
-class LoggingButton extends React.Component {
- // This syntax ensures `this` is bound within handleClick.
- // Warning: this is *experimental* syntax.
- handleClick = () => {
- console.log('this is:', this);
- }
-
- render() {
- return (
-
- );
- }
-}
-```
+`embed:handling-events/login-button-public-class-field-example.js`
This syntax is enabled by default in [Create React App](https://github.com/facebookincubator/create-react-app).
If you aren't using class fields syntax, you can use an [arrow function](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions) in the callback:
-```js{7-9}
-class LoggingButton extends React.Component {
- handleClick() {
- console.log('this is:', this);
- }
-
- render() {
- // This syntax ensures `this` is bound within handleClick
- return (
-
- );
- }
-}
-```
+`embed:handling-events/login-button-arrow-function.js`
The problem with this syntax is that a different callback is created each time the `LoggingButton` renders. In most cases, this is fine. However, if this callback is passed as a prop to lower components, those components might do an extra re-rendering. We generally recommend binding in the constructor or using the class fields syntax, to avoid this sort of performance problem.
diff --git a/examples/handling-events/action-link-example.js b/examples/handling-events/action-link-example.js
new file mode 100644
index 00000000000..1635be28427
--- /dev/null
+++ b/examples/handling-events/action-link-example.js
@@ -0,0 +1,13 @@
+// highlight-range{2-5,8}
+function ActionLink() {
+ function handleClick(e) {
+ e.preventDefault();
+ console.log('The link was clicked.');
+ }
+
+ return (
+
+ Click me
+
+ );
+}
diff --git a/examples/handling-events/login-button-arrow-function.js b/examples/handling-events/login-button-arrow-function.js
new file mode 100644
index 00000000000..5546af99f34
--- /dev/null
+++ b/examples/handling-events/login-button-arrow-function.js
@@ -0,0 +1,15 @@
+// highlight-range{7-9}
+class LoggingButton extends React.Component {
+ handleClick() {
+ console.log('this is:', this);
+ }
+
+ render() {
+ // This syntax ensures `this` is bound within handleClick
+ return (
+
+ );
+ }
+}
diff --git a/examples/handling-events/login-button-public-class-field-example.js b/examples/handling-events/login-button-public-class-field-example.js
new file mode 100644
index 00000000000..28d4dc557bc
--- /dev/null
+++ b/examples/handling-events/login-button-public-class-field-example.js
@@ -0,0 +1,14 @@
+// highlight-range{2-6}
+class LoggingButton extends React.Component {
+ // This syntax ensures `this` is bound within handleClick.
+ // Warning: this is *experimental* syntax.
+ handleClick = () => {
+ console.log('this is:', this);
+ };
+
+ render() {
+ return (
+
+ );
+ }
+}
diff --git a/examples/handling-events/toggle-example.css b/examples/handling-events/toggle-example.css
new file mode 100644
index 00000000000..ce71bb9c972
--- /dev/null
+++ b/examples/handling-events/toggle-example.css
@@ -0,0 +1,3 @@
+body {
+ padding: 5px
+}
\ No newline at end of file
diff --git a/examples/handling-events/toggle-example.js b/examples/handling-events/toggle-example.js
new file mode 100644
index 00000000000..ea29a20a1ff
--- /dev/null
+++ b/examples/handling-events/toggle-example.js
@@ -0,0 +1,34 @@
+/* hide-range{1-4} */
+// highlight-range{10,11,14-18,22}
+import React from 'react';
+import ReactDOM from 'react-dom';
+import './toggle-example.css';
+
+class Toggle extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = {isToggleOn: true};
+
+ // This binding is necessary to make `this` work in the callback
+ this.handleClick = this.handleClick.bind(this);
+ }
+
+ handleClick() {
+ this.setState(state => ({
+ isToggleOn: !state.isToggleOn,
+ }));
+ }
+
+ render() {
+ return (
+
+ );
+ }
+}
+
+ReactDOM.render(
+ ,
+ document.getElementById('root')
+);
diff --git a/package.json b/package.json
index b22d19551fe..8e2e887c468 100644
--- a/package.json
+++ b/package.json
@@ -31,10 +31,10 @@
"gatsby-plugin-twitter": "^2.0.0",
"gatsby-remark-code-repls": "^2.0.0",
"gatsby-remark-copy-linked-files": "^2.0.0",
- "gatsby-remark-embed-snippet": "^3.0.0",
+ "gatsby-remark-embed-snippet": "4.1.6",
"gatsby-remark-external-links": "^0.0.4",
"gatsby-remark-images": "^2.0.0",
- "gatsby-remark-prismjs": "^3.0.2",
+ "gatsby-remark-prismjs": "3.3.12",
"gatsby-remark-responsive-iframe": "^2.0.0",
"gatsby-remark-smartypants": "^2.0.0",
"gatsby-source-filesystem": "^2.0.0",
diff --git a/yarn.lock b/yarn.lock
index 480594945e9..1edd77026d3 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -732,6 +732,13 @@
dependencies:
regenerator-runtime "^0.12.0"
+"@babel/runtime@^7.5.5":
+ version "7.5.5"
+ resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.5.5.tgz#74fba56d35efbeca444091c7850ccd494fd2f132"
+ integrity sha512-28QvEGyQyNkB0/m2B4FU7IEZGK2NUrcMtT6BZEFALTguLk+AUT6ofsHtPk5QyjAdUkpMJ+/Em+quwz4HOt30AQ==
+ dependencies:
+ regenerator-runtime "^0.13.2"
+
"@babel/template@7.0.0-beta.44":
version "7.0.0-beta.44"
resolved "http://registry.npmjs.org/@babel/template/-/template-7.0.0-beta.44.tgz#f8832f4fdcee5d59bf515e595fc5106c529b394f"
@@ -5489,15 +5496,15 @@ gatsby-remark-copy-linked-files@^2.0.0:
probe-image-size "^4.0.0"
unist-util-visit "^1.3.0"
-gatsby-remark-embed-snippet@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/gatsby-remark-embed-snippet/-/gatsby-remark-embed-snippet-3.0.0.tgz#9ed032d51274bbabe7307e6e03879cd49941818f"
- integrity sha512-vqxx15/J+AylOvpVAfKhYDr/TGGnJ7DNx3ZdukEaQrT/aGc+/8ztfir61+gsHIFa8qIpmpoTpXvUAEbcK0lzIg==
+gatsby-remark-embed-snippet@4.1.6:
+ version "4.1.6"
+ resolved "https://registry.yarnpkg.com/gatsby-remark-embed-snippet/-/gatsby-remark-embed-snippet-4.1.6.tgz#c7a6a9b6f6724303528303274ef8a9ce19e30bc1"
+ integrity sha512-37618jCRC7iDpPxEkhieDUWHDAMaNT+unyV7pqUro3+zN6nvUeDzwWkCFQzg1QcAWv/uSqlDkIBrfm5wxcR92w==
dependencies:
- "@babel/runtime" "^7.0.0"
+ "@babel/runtime" "^7.5.5"
normalize-path "^2.1.1"
parse-numeric-range "^0.0.2"
- unist-util-map "^1.0.3"
+ unist-util-map "^1.0.5"
gatsby-remark-external-links@^0.0.4:
version "0.0.4"
@@ -5521,14 +5528,14 @@ gatsby-remark-images@^2.0.0:
unist-util-select "^1.5.0"
unist-util-visit-parents "^2.0.1"
-gatsby-remark-prismjs@^3.0.2:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/gatsby-remark-prismjs/-/gatsby-remark-prismjs-3.0.2.tgz#38a67c4e020ac26102e850ccefbe8b0e696501dc"
- integrity sha512-tjgGzDVkDX3EtBgKI8uNxArNjLF97M3ipMzh1PLGtIn1naVrixw36xV7s6BkiZigdpybj9rjF7mvBKPtZekh2w==
+gatsby-remark-prismjs@3.3.12:
+ version "3.3.12"
+ resolved "https://registry.yarnpkg.com/gatsby-remark-prismjs/-/gatsby-remark-prismjs-3.3.12.tgz#4239bb48a5e2eb5fcff5adbbac1a6821012bd9bf"
+ integrity sha512-PE744uWg0M09hFZSOpQac+oUpmwKHAYJc0unLIszNdXvbihPL8rhi9aahKiz3EvQDbQ35WNHHPOsS/OjtegmIw==
dependencies:
- "@babel/runtime" "^7.0.0"
+ "@babel/runtime" "^7.5.5"
parse-numeric-range "^0.0.2"
- unist-util-visit "^1.3.0"
+ unist-util-visit "^1.4.1"
gatsby-remark-responsive-iframe@^2.0.0:
version "2.0.5"
@@ -10491,6 +10498,11 @@ regenerator-runtime@^0.12.0:
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz#fa1a71544764c036f8c49b13a08b2594c9f8a0de"
integrity sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg==
+regenerator-runtime@^0.13.2:
+ version "0.13.3"
+ resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz#7cf6a77d8f5c6f60eb73c5fc1955b2ceb01e6bf5"
+ integrity sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==
+
regenerator-transform@^0.13.3:
version "0.13.3"
resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.13.3.tgz#264bd9ff38a8ce24b06e0636496b2c856b57bcbb"
@@ -12487,6 +12499,13 @@ unist-util-map@^1.0.3:
dependencies:
object-assign "^4.0.1"
+unist-util-map@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/unist-util-map/-/unist-util-map-1.0.5.tgz#701069b72e1d1cc02db265502a5e82b77c2eb8b7"
+ integrity sha512-dFil/AN6vqhnQWNCZk0GF/G3+Q5YwsB+PqjnzvpO2wzdRtUJ1E8PN+XRE/PRr/G3FzKjRTJU0haqE0Ekl+O3Ag==
+ dependencies:
+ object-assign "^4.0.1"
+
unist-util-modify-children@^1.0.0:
version "1.1.2"
resolved "https://registry.yarnpkg.com/unist-util-modify-children/-/unist-util-modify-children-1.1.2.tgz#c7f1b91712554ee59c47a05b551ed3e052a4e2d1"
@@ -12539,6 +12558,13 @@ unist-util-visit@^1.0.0, unist-util-visit@^1.1.0, unist-util-visit@^1.1.3, unist
dependencies:
unist-util-visit-parents "^2.0.0"
+unist-util-visit@^1.4.1:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-1.4.1.tgz#4724aaa8486e6ee6e26d7ff3c8685960d560b1e3"
+ integrity sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw==
+ dependencies:
+ unist-util-visit-parents "^2.0.0"
+
universalify@^0.1.0:
version "0.1.2"
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"