Last active
June 18, 2021 03:51
-
-
Save syusui-s/5ed604b98220efcddc60abc07bef0b3c to your computer and use it in GitHub Desktop.
React + UserScript 名前空間の汚染/モジュールバンドラー/JSX/トランスパイラなしにReactをUserScriptで使う方法 / Example of using React in UserScript without global namespace pollution, module bundler, JSX and transpiler.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // ==UserScript== | |
| // @name Use React in UserScript | |
| // @namespace http://tampermonkey.net/ | |
| // @version 0.1 | |
| // @description This example shows how to use React in UserScript without global namespace pollution. | |
| // @author You | |
| // @match * | |
| // @grant none | |
| // ==/UserScript== | |
| (async function() { | |
| const tryWithTimeout = (promise, ms) => Promise.race([ | |
| new Promise((_, reject) => setTimeout(() => reject(new Error(`Timeout: ${ms} ms`)), ms)), | |
| promise, | |
| ]); | |
| try { | |
| // This example uses async/await and dynamic imports. | |
| const [ | |
| { default: React, useState }, | |
| { default: ReactDOM }, | |
| { default: hyperx } | |
| ] = await tryWithTimeout(Promise.all([ | |
| import('https://cdn.skypack.dev/react@17?min'), | |
| import('https://cdn.skypack.dev/react-dom@17?min'), | |
| import('https://cdn.skypack.dev/[email protected]?min')]), 5000); | |
| // This example uses choojs/hyperx for writing elements and components. | |
| // Ref: <https://github.com/choojs/hyperx> | |
| // | |
| // There are some options: | |
| // | |
| // * call `createElement` directly (https://reactjs.org/docs/react-without-jsx.html) | |
| // const h = React.createElement; | |
| // h('div', { className: 'hello' }, hello) | |
| // * htm <https://github.com/developit/htm> (★6.5k) | |
| // const html = htm.bind(React.createElement); | |
| // html`<div class="hello">${hello}</div>` | |
| // * react-hyperscript (★626) | |
| // h('div.hello', hello) | |
| // * njsx (★27) | |
| // import {p} from 'njsx-react' | |
| // div.hello(hello) | |
| // * NoJSX (★6) | |
| // | |
| // Alternatives to React: | |
| // * preact (★28.3k) | |
| // You don't need ReactDOM (>= 100kB). | |
| // About 3.6kB | |
| // * hyperapp v2 (★18.3k) | |
| // 3kB framework. | |
| // * lit-html <https://lit-html.polymer-project.org/> (★7.0k) | |
| // html`<div class="hello">${hello}</div>` | |
| const hx = hyperx( | |
| (component, properties, children) => React.createElement.apply(null, [component, properties].concat(children)), | |
| { createFragment(children) { React.createElement.apply(null, [React.Fragment, {}].concat(children)); } }, | |
| ); | |
| const Hello = () => { | |
| const [count, setCount] = useState(0); | |
| return hx` | |
| <div style=${{ position: 'absolute', top: 0, left: 0, zIndex: 10000, }}> | |
| <h1>Hello. ${count}</h1> | |
| <button onClick=${() => setCount(v => v + 1)}>Click</button> | |
| </div> | |
| `; | |
| }; | |
| const domContainer = document.createElement('div'); | |
| document.body.appendChild(domContainer); | |
| // FYI <Hello/> doesn't work. we must specify real component in form of `<${Hello}>` since hyperx doesn't recognize scope. | |
| // FYI <${Hello} /> doesn't work. In hyperx, spaces after component is not allowed if empty element. | |
| // FYI <${Hello} prop=${prop} /> doesn't work. Instead you should use <${Hello} prop=${prop}></${Hello}>. | |
| ReactDOM.render(hx`<${Hello}/>`, domContainer); | |
| } catch (e) { | |
| console.error(e); | |
| } | |
| })(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment