From ac5181bef8462c67234958f220e2aeec7bf920ab Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 7 Mar 2019 09:10:31 -0500 Subject: [PATCH] add section on context --- .../01-context-api/app-a/App.svelte | 13 +++++ .../01-context-api/app-a/Map.svelte | 48 ++++++++++++++++++ .../01-context-api/app-a/MapMarker.svelte | 17 +++++++ .../15-context/01-context-api/app-a/mapbox.js | 8 +++ .../01-context-api/app-b/App.svelte | 13 +++++ .../01-context-api/app-b/Map.svelte | 50 +++++++++++++++++++ .../01-context-api/app-b/MapMarker.svelte | 19 +++++++ .../15-context/01-context-api/app-b/mapbox.js | 8 +++ .../15-context/01-context-api/text.md | 47 +++++++++++++++++ site/content/tutorial/15-context/meta.json | 3 ++ site/content/tutorial/99-todo/99-todo/text.md | 1 + site/now.json | 3 +- site/rollup.config.js | 4 +- site/src/components/Repl/Output/Viewer.svelte | 9 +++- 14 files changed, 239 insertions(+), 4 deletions(-) create mode 100644 site/content/tutorial/15-context/01-context-api/app-a/App.svelte create mode 100644 site/content/tutorial/15-context/01-context-api/app-a/Map.svelte create mode 100644 site/content/tutorial/15-context/01-context-api/app-a/MapMarker.svelte create mode 100644 site/content/tutorial/15-context/01-context-api/app-a/mapbox.js create mode 100644 site/content/tutorial/15-context/01-context-api/app-b/App.svelte create mode 100644 site/content/tutorial/15-context/01-context-api/app-b/Map.svelte create mode 100644 site/content/tutorial/15-context/01-context-api/app-b/MapMarker.svelte create mode 100644 site/content/tutorial/15-context/01-context-api/app-b/mapbox.js create mode 100644 site/content/tutorial/15-context/01-context-api/text.md create mode 100644 site/content/tutorial/15-context/meta.json diff --git a/site/content/tutorial/15-context/01-context-api/app-a/App.svelte b/site/content/tutorial/15-context/01-context-api/app-a/App.svelte new file mode 100644 index 0000000000..ea1ba4c7ae --- /dev/null +++ b/site/content/tutorial/15-context/01-context-api/app-a/App.svelte @@ -0,0 +1,13 @@ + + + + + + + + + + \ No newline at end of file diff --git a/site/content/tutorial/15-context/01-context-api/app-a/Map.svelte b/site/content/tutorial/15-context/01-context-api/app-a/Map.svelte new file mode 100644 index 0000000000..888f42da39 --- /dev/null +++ b/site/content/tutorial/15-context/01-context-api/app-a/Map.svelte @@ -0,0 +1,48 @@ + + + + +
+ {#if map} + + {/if} +
\ No newline at end of file diff --git a/site/content/tutorial/15-context/01-context-api/app-a/MapMarker.svelte b/site/content/tutorial/15-context/01-context-api/app-a/MapMarker.svelte new file mode 100644 index 0000000000..9bebce66e4 --- /dev/null +++ b/site/content/tutorial/15-context/01-context-api/app-a/MapMarker.svelte @@ -0,0 +1,17 @@ + \ No newline at end of file diff --git a/site/content/tutorial/15-context/01-context-api/app-a/mapbox.js b/site/content/tutorial/15-context/01-context-api/app-a/mapbox.js new file mode 100644 index 0000000000..55b4200038 --- /dev/null +++ b/site/content/tutorial/15-context/01-context-api/app-a/mapbox.js @@ -0,0 +1,8 @@ +import mapbox from 'mapbox-gl'; + +// https://docs.mapbox.com/help/glossary/access-token/ +mapbox.accessToken = MAPBOX_ACCESS_TOKEN; + +const key = {}; + +export { mapbox, key }; \ No newline at end of file diff --git a/site/content/tutorial/15-context/01-context-api/app-b/App.svelte b/site/content/tutorial/15-context/01-context-api/app-b/App.svelte new file mode 100644 index 0000000000..ea1ba4c7ae --- /dev/null +++ b/site/content/tutorial/15-context/01-context-api/app-b/App.svelte @@ -0,0 +1,13 @@ + + + + + + + + + + \ No newline at end of file diff --git a/site/content/tutorial/15-context/01-context-api/app-b/Map.svelte b/site/content/tutorial/15-context/01-context-api/app-b/Map.svelte new file mode 100644 index 0000000000..0282cbc311 --- /dev/null +++ b/site/content/tutorial/15-context/01-context-api/app-b/Map.svelte @@ -0,0 +1,50 @@ + + + + +
+ {#if map} + + {/if} +
\ No newline at end of file diff --git a/site/content/tutorial/15-context/01-context-api/app-b/MapMarker.svelte b/site/content/tutorial/15-context/01-context-api/app-b/MapMarker.svelte new file mode 100644 index 0000000000..c936652507 --- /dev/null +++ b/site/content/tutorial/15-context/01-context-api/app-b/MapMarker.svelte @@ -0,0 +1,19 @@ + \ No newline at end of file diff --git a/site/content/tutorial/15-context/01-context-api/app-b/mapbox.js b/site/content/tutorial/15-context/01-context-api/app-b/mapbox.js new file mode 100644 index 0000000000..55b4200038 --- /dev/null +++ b/site/content/tutorial/15-context/01-context-api/app-b/mapbox.js @@ -0,0 +1,8 @@ +import mapbox from 'mapbox-gl'; + +// https://docs.mapbox.com/help/glossary/access-token/ +mapbox.accessToken = MAPBOX_ACCESS_TOKEN; + +const key = {}; + +export { mapbox, key }; \ No newline at end of file diff --git a/site/content/tutorial/15-context/01-context-api/text.md b/site/content/tutorial/15-context/01-context-api/text.md new file mode 100644 index 0000000000..3d095dd679 --- /dev/null +++ b/site/content/tutorial/15-context/01-context-api/text.md @@ -0,0 +1,47 @@ +--- +title: setContext and getContext +--- + +The context API provides a mechanism for components to 'talk' to each other without passing around data and functions as props, or dispatching lots of events. It's an advanced feature, but a useful one. + +Take this example app using a [Mapbox GL](https://docs.mapbox.com/mapbox-gl-js/overview/) map. We'd like to display the markers, using the `` component, but we don't want to have to pass around a reference to the underlying Mapbox instance as a prop on each component. + +There are two halves to the context API — `setContext` and `getContext`. If a component calls `setContext(key, context)`, then any *child* component can retrieve the context with `const context = getContext(key)`. + +Let's set the context first. In `Map.svelte`, import `setContext` from `svelte` and `key` from `mapbox.js` and call `setContext`: + +```js +import { onMount, setContext } from 'svelte'; +import { mapbox, key } from './mapbox.js'; + +setContext(key, { + getMap: () => map +}); +``` + +The context object can be anything you like. Like [lifecycle functions](tutorial/onmount), `setContext` and `getContext` must be called during component initialisation; since `map` isn't created until the component has mounted, our context object contains a `getMap` function rather than `map` itself. + +On the other side of the equation, in `MapMarker.svelte`, we can now get a reference to the Mapbox instance: + +```js +import { getContext } from 'svelte'; +import { mapbox, key } from './mapbox.js'; + +const { getMap } = getContext(key); +const map = getMap(); +``` + +The markers can now add themselves to the map. + +> A more finished version of `` would also handle removal and prop changes, but we're only demonstrating context here. + + +## Context keys + +In `mapbox.js` you'll see this line: + +```js +const key = {}; +``` + +We can use anything as a key — we could do `setContext('mapbox', ...)` for example. The downside of using a string is that different component libraries might accidentally use the same one; using an object literal means the keys are guaranteed not to conflict in any circumstance, even when you have multiple different contexts operating across many component layers. \ No newline at end of file diff --git a/site/content/tutorial/15-context/meta.json b/site/content/tutorial/15-context/meta.json new file mode 100644 index 0000000000..d3bd862676 --- /dev/null +++ b/site/content/tutorial/15-context/meta.json @@ -0,0 +1,3 @@ +{ + "title": "Context API" +} \ No newline at end of file diff --git a/site/content/tutorial/99-todo/99-todo/text.md b/site/content/tutorial/99-todo/99-todo/text.md index 8916aeeb00..683b4fa15b 100644 --- a/site/content/tutorial/99-todo/99-todo/text.md +++ b/site/content/tutorial/99-todo/99-todo/text.md @@ -113,6 +113,7 @@ Maybe lifecycle should go first, since we're using `onMount` in the `this` demo? * [x] Custom JS transitions * [x] Thunk(?) transitions * [x] `on:introstart` etc +* [ ] Local transitions ## Animations diff --git a/site/now.json b/site/now.json index 2840898344..aa1684a891 100644 --- a/site/now.json +++ b/site/now.json @@ -6,7 +6,8 @@ "NODE_ENV": "production", "BASEURL": "https://v3.svelte.technology", "GITHUB_CLIENT_ID": "@svelte-gist-client-id-v3", - "GITHUB_CLIENT_SECRET": "@svelte-gist-client-secret-v3" + "GITHUB_CLIENT_SECRET": "@svelte-gist-client-secret-v3", + "MAPBOX_ACCESS_TOKEN": "@svelte-mapbox-access-token" }, "files": [ "__sapper__/build", diff --git a/site/rollup.config.js b/site/rollup.config.js index 48f5559a8c..d39db86c0c 100644 --- a/site/rollup.config.js +++ b/site/rollup.config.js @@ -1,3 +1,4 @@ +import 'dotenv/config'; import resolve from 'rollup-plugin-node-resolve'; import replace from 'rollup-plugin-replace'; import commonjs from 'rollup-plugin-commonjs'; @@ -19,7 +20,8 @@ export default { plugins: [ replace({ 'process.browser': true, - 'process.env.NODE_ENV': JSON.stringify(mode) + 'process.env.NODE_ENV': JSON.stringify(mode), + 'process.env.MAPBOX_ACCESS_TOKEN': JSON.stringify(process.env.MAPBOX_ACCESS_TOKEN) }), svelte({ dev, diff --git a/site/src/components/Repl/Output/Viewer.svelte b/site/src/components/Repl/Output/Viewer.svelte index 42f3e31326..eec904526f 100644 --- a/site/src/components/Repl/Output/Viewer.svelte +++ b/site/src/components/Repl/Output/Viewer.svelte @@ -63,9 +63,14 @@ const styles = document.querySelectorAll('style.svelte'); let i = styles.length; while (i--) styles[i].parentNode.removeChild(styles[i]); - `) + `); + + await proxy.eval(` + // needed for context API tutorial + window.MAPBOX_ACCESS_TOKEN = process.env.MAPBOX_ACCESS_TOKEN; + + ${$bundle.dom.code} - await proxy.eval(`${$bundle.dom.code} if (window.component) { try { window.component.$destroy();