refusejs
v1.0.3
Published
 The name of `refuse` comes from its main action: `fuse` (join or blend) multiple components to form a single working app. Fun fact: it also me
Readme
Refuse 
The name of refuse comes from its main action: fuse (join or blend) multiple components to form a single working app. Fun fact: it also means trash, or refers to the action of being not willing to do something in English)
Note: This library is a work-in-progress. Some features are not available yet. See Feature lists for more details.
Key points:
- Same modern API as React.js
- Full typescript support
- No JSX
- No build tool, no bundler, no transpiler required
Different from React:
- No class component supported
- No longer need to return single root element, so
Fragmentuse cases now narrow down to key-ed diff only. - Ref works on component as well, and auto assign to the root element of the component.
- If the component have multiple root, it will point to the
DocumentFragment, which will be empty (and useless) after moving its child to the DOM. Read more - (Don't need to wrap component in forwardRef, just) use the second parameter of component to assign it to a specific element.
- If the component have multiple root, it will point to the
- Component can return
number[],string[],fuse[]or evenstring[][]to render multiple elements.- Component can return
null,undefined,falseto skip rendering.
- Component can return
About syntax:
- Spread props:
<div ...${props}>instead of<div {...props}> - HTML's quotes now optional:
<div class=foo> - Shorthand for component end-tags:
<${Foo}>bar<//> - Comment:
<!-- comment -->
Syntax highlighting support:
- Intellij IDEA (WebStorm,...): supported by default
- VSCode: lit-html
Have you ever wondered how React.js works internally? Reading the source code of
refuseis a good way to learn how it works.
Try it out now
Getting started
npm i -S refusejsimport {useState, fuse,render} from "refusejs"
import type {RefuseComponent} from "refusejs"
interface Props {
someThing: string
}
const Component: RefuseComponent<Props> = (props, ref) => {
const [state, setState] = useState(0)
useEffect(() => {
const timer = setInterval(() => setState(state + 1), 1000)
return () => clearInterval(timer)
}, [])
return fuse`
<div class=foo ...${props} foo=${state}>
${props.children}
<${A}>Something...<//>
<button onclick=${() => setState(state + 1)}>Click me</button>
${state > 300 && fuse`<div>
Yeah
</div>`}
<!-- some comment -->
</div>
`
}
render(Component, document.getElementById('root'))Or
<script src="https://unpkg.com/refusejs@latest/dist/refuse.umd.js"></script>
<script>
const {render, fuse} = Refuse;
render(
() => fuse`
<div>
<h1>Hello, world!</h1>
<p>It's a beautiful day.</p>
</div>
`,
document.getElementById('root2')
);
</script>or
<script type="module">
import * as Refuse from 'https://unpkg.com/refusejs@latest/dist/refuse.modern.js'; // Support only modern browsers
// import * as Refuse from 'https://unpkg.com/refusejs@latest/dist/refuse.module.js'; // Support all browsers
Refuse.render(
() => Refuse.fuse`
<div>
<h1>Hello, world!</h1>
<p>It's a beautiful day.</p>
</div>
`,
document.getElementById('root')
);
</script>Feature lists:
- [x] TypeScript
- [x] Jsx to HyperScript using
htm - [x] render
- [x] Custom components with props
- [x] Custom components with children
- [x] useState
- [X] Automatic state update batching
- [ ] flushSync
- [x] useEffect with cleanup
- [x] Unmount components
- [x] Component Tree
- [x] Render: dirty mark, compare
- [ ] Render: keys
- [x] Conditional rendering
- [x] DOM diffing/patching
- [x] useLayoutEffect
- [x] useMemo, useCallback, useRef
- [x] memo
- [x] Fragment
- [x] JSX Embedding Expression
- [x] DOM Ref
- [x] React.forwardRef
- [ ] Render multiple Refuse instances
- [ ] Error Boundary
- [ ] Concurrent Mode, useTransition
- [ ] useContext
- [ ] useReducer
- [ ] Test utils, write tests
- [ ] Portal
- [ ] Server-side rendering
- [ ] Synthetic Event
- [ ] Devtools, debugger, HMR - Hot reload
- [ ] Router
- [ ] useDeferredValue
- [ ] Suspense
- [ ] useImperativeHandle
- [ ] useDebugValue
- [ ] useId
- [ ] useSyncExternalStore
- [ ] Dynamic import, React.lazy
- [ ] Production build
- [ ] Profiler
- [ ] Linter
- [ ] Type checker on tagged template
- [ ] useEvent
Development
Watch refuse package
npm i --lockfile-only
npm link
npm run devRun example1
cd demo/example1
npm i --lockfile-only
npm link refusejs
npm run devAnd follow instructions.
