Skip to content

Instantly share code, notes, and snippets.

@syusui-s
Last active June 18, 2021 03:51
Show Gist options
  • Select an option

  • Save syusui-s/5ed604b98220efcddc60abc07bef0b3c to your computer and use it in GitHub Desktop.

Select an option

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.
// ==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