Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/huynhducduy/refuse
Yet another fast and lightweight alternative of React.js
https://github.com/huynhducduy/refuse
dom hooks hyperscript jsx preact react reactjs reconciliation solid virtual-dom
Last synced: 3 months ago
JSON representation
Yet another fast and lightweight alternative of React.js
- Host: GitHub
- URL: https://github.com/huynhducduy/refuse
- Owner: huynhducduy
- License: apache-2.0
- Created: 2022-06-12T23:22:16.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2024-03-08T22:17:03.000Z (11 months ago)
- Last Synced: 2024-10-01T04:04:45.819Z (4 months ago)
- Topics: dom, hooks, hyperscript, jsx, preact, react, reactjs, reconciliation, solid, virtual-dom
- Language: TypeScript
- Homepage:
- Size: 249 KB
- Stars: 6
- Watchers: 3
- Forks: 0
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Refuse [![npm version](https://badge.fury.io/js/refusejs.svg)](https://badge.fury.io/js/refusejs)
![Refuse](https://user-images.githubusercontent.com/12293622/219362480-f01fec20-f405-44e4-af0f-10cfc5712c30.png)
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](#feature-lists) for more details.[![Built with WeBuild](https://raw.githubusercontent.com/webuild-community/badge/master/svg/WeBuild.svg)](https://webuild.community) [![From Vietnam with <3](https://raw.githubusercontent.com/webuild-community/badge/master/svg/love.svg)](https://webuild.community)
Key points:
- Same modern API as React.js
- Full typescript support
- No JSX
- No build tool, no bundler, no transpiler requiredDifferent from React:
- No class component supported
- No longer need to return single root element, so `Fragment` use 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](https://developer.mozilla.org/en-US/docs/Web/API/DocumentFragment#usage_notes)
- (Don't need to wrap component in forwardRef, just) use the second parameter of component to assign it to a specific element.
- Component can return `number[]`,`string[]`,`fuse[]` or even `string[][]` to render multiple elements.
- Component can return `null`,`undefined`,`false` to skip rendering.About syntax:
- Spread props: `` instead of ``
- HTML's quotes now optional: ``
- Shorthand for component end-tags: `<${Foo}>bar/>`
- Comment: ``Syntax highlighting support:
- Intellij IDEA (WebStorm,...): supported by default
- VSCode: [lit-html](https://marketplace.visualstudio.com/items?itemName=bierner.lit-html)> Have you ever wondered how React.js works internally? Reading the source code of `refuse` is a good way to learn how it works.
## Try it out now
[![Whac-a-mole with Refuse](https://user-images.githubusercontent.com/12293622/219870837-306fd0ae-479c-442f-a402-325a7d2f72bd.png)](https://codepen.io/huynhducduy/pen/VwGvjbv)
[Whac-a-mole with Refuse](https://codepen.io/huynhducduy/pen/VwGvjbv)
[With Vite](https://codesandbox.io/p/sandbox/refuse-vite-beb3gc)
[Without bundler](https://codepen.io/huynhducduy/pen/wvEBNPo)
## Getting started
```
npm i -S refusejs
``````ts
import {useState, fuse,render} from "refusejs"
import type {RefuseComponent} from "refusejs"interface Props {
someThing: string
}const Component: RefuseComponent = (props, ref) => {
const [state, setState] = useState(0)useEffect(() => {
const timer = setInterval(() => setState(state + 1), 1000)
return () => clearInterval(timer)
}, [])return fuse`
${props.children}
<${A}>Something.../>
setState(state + 1)}>Click me
${state > 300 && fuse``}
Yeah
`
}render(Component, document.getElementById('root'))
```Or
```html
const {render, fuse} = Refuse;
render(
() => fuse`
<div>
<h1>Hello, world!</h1>
<p>It's a beautiful day.</p>
</div>
`,
document.getElementById('root2')
);```
or
```html
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 browsersRefuse.render(
() => Refuse.fuse`
<div>
<h1>Hello, world!</h1>
<p>It's a beautiful day.</p>
</div>
`,
document.getElementById('root')
);```
## 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 dev
```Run `example1`
```
cd demo/example1
npm i --lockfile-only
npm link refusejs
npm run dev
```And follow instructions.