Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/toyobayashi/reactivuety
Use vue composition API with react
https://github.com/toyobayashi/reactivuety
Last synced: 28 days ago
JSON representation
Use vue composition API with react
- Host: GitHub
- URL: https://github.com/toyobayashi/reactivuety
- Owner: toyobayashi
- Created: 2020-12-07T09:52:03.000Z (almost 4 years ago)
- Default Branch: main
- Last Pushed: 2022-03-09T09:13:31.000Z (over 2 years ago)
- Last Synced: 2024-09-18T15:42:25.179Z (about 2 months ago)
- Language: TypeScript
- Size: 406 KB
- Stars: 5
- Watchers: 2
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# reactivuety
Write react in vue way.
[API Documentation](https://github.com/toyobayashi/reactivuety/blob/main/docs/api/index.md)
[中文](https://github.com/toyobayashi/reactivuety/blob/main/README_CN.md)
## Install
```
npm install @tybys/reactivuety
```or
```html
```
## Compare with Vue
Markdown example:
Vue:
```vue
import { ref, computed, defineComponent } from 'vue'
import * as marked from 'marked'
import * as debounce from 'lodash/debounce'export default defineComponent({
setup () {
const input = ref('# hello')
const compiledMarkdown = computed(() => marked(input.value))const update = debounce(function(e) {
input.value = e.target.value;
}, 300)return { input, compiledMarkdown, update }
}
})```
Use `defineComponent`, the first argument is setup function, which returns a react renden function.
```jsx
// import ...
import * as React from 'react'
import { defineComponent, ref, computed, Textarea } from '@tybys/reactivuety'export default defineComponent((vueProps) => {
const input = ref('# hello')
const compiledMarkdown = computed(() => ({ __html: marked(input.value) }))const update = debounce((e) => {
input.value = e.target.value
}, 300)return (reactProps, ref) => ( // <-- returns a react renden function
// use other react hooks here
)
})
```No bundler:
```html
(function () {
var defineComponent = reactivuety.defineComponent;
var ref = reactivuety.ref;
var computed = reactivuety.computed;
var Textarea = reactivuety.Textarea;
var h = React.createElement;
var debounce = _.debounce;var MarkdownView = defineComponent(function (vueProps) {
var input = ref('# hello');var compiledMarkdown = computed(function () {
return { __html: marked(input.value) };
});var update = debounce(function (e) {
input.value = e.target.value;
}, 300);return function (reactProps, ref) {
// use other react hooks here
return h('div', { id: 'editor' },
h(Textarea, { value: input.value, onInput: update }),
h('div', { dangerouslySetInnerHTML: compiledMarkdown.value })
);
};
});
ReactDOM.render(h(MarkdownView), document.body);
})();```
Use `defineComponent`, the first argument is setup function, which returns an object contains vue reactive objects, the second argument is a react function component render function whose with first argument is the object returned by the setup function.
```jsx
// import ...
export default defineComponent((vueProps) => {
const input = ref('# hello')
const compiledMarkdown = computed(() => ({ __html: marked(input.value) }))const update = debounce((e) => {
input.value = e.target.value
}, 300)return { input, compiledMarkdown, update }
}, (state, reactProps, ref) => (
// use other react hooks here
))
```Use `useSetup` hook, the first argument is setup function, which returns an object contains vue reactive objects, the second argument is react props.
```jsx
// import ...
import * as React from 'react'
import { useSetup, ref, computed, Textarea } from '@tybys/reactivuety'export default (reactProps) => {
const state = useSetup(
(vueProps) => {
const input = ref('# hello')
const compiledMarkdown = computed(() => ({ __html: marked(input.value) }))const update = debounce((e) => {
input.value = e.target.value
}, 300)return { input, compiledMarkdown, update }
},
reactProps // <-- pass react props
)// use other react hooks here
return (
)
}
```Use `useSetup` hook, the first argument is setup function, which returns a render function, the second argument is react props.
```jsx
// import ...
export default (reactProps, refOrContext) => {
const render = useSetup(
(vueProps) => {
const input = ref('# hello')
const compiledMarkdown = computed(() => ({ __html: marked(input.value) }))const update = debounce((e) => {
input.value = e.target.value
}, 300)return (reactProps, refOrContext) => (
// use other react hooks here
)
},
reactProps
)return render(reactProps, refOrContext)
}
```## Other usage
### nextTick
Similar to vue 3.
``` jsx
import { nextTick, ref, defineComponent } from '@tybys/reactivuety'
export default defineComponent(() => {
const a = ref('a')
const onClick = () => {
a.value = 'b'
console.log(document.getElementById('a').innerHTML) // a
nextTick(() => {
console.log(document.getElementById('a').innerHTML) // b
})
}return () => (
{a.value})
})
```### Lifecycles
Similar to vue 3.
``` jsx
import {
onBeforeMount,
onBeforeUnmount,
onBeforeUpdate,
onErrorCaptured,
onMounted,
onRenderTracked,
onRenderTriggered,
onUnmounted,
onUpdated,
defineComponent
} from '@tybys/reactivuety'export default defineComponent(() => {
onBeforeMount(() => {})
onBeforeUnmount(() => {})
onBeforeUpdate(() => {})
onErrorCaptured((err, type) => {}) // <-- No instance
onMounted(() => {})
onRenderTracked((e) => {})
onRenderTriggered((e) => {})
onUnmounted(() => {})
onUpdated(() => {})
// ...
})
```### Async component
Similar to vue 3. But no `suspensible` option.
```jsx
import { defineAsyncComponent } from '@tybys/reactivuety'const MyComponent = defineAsyncComponent(() => import('./MyComponent'))
const MyComponent2 = defineAsyncComponent({
loader: () => import('./MyComponent'),
delay: 200,
loadingComponent: () => (),
errorComponent: ({ error }) => ({error?.message}),
timeout: Infinity
onError: (error, retry, fail) => {}
})
```### Provide / Inject
Similar to vue 3.
In parent:
```jsx
import { provide, ref, defineComponent } from '@tybys/reactivuety'
export default defineComponent(() => {
const a = ref('')
provide('a', a)
// ...
})
```In children (can be deep):
```jsx
import { inject, defineComponent } from '@tybys/reactivuety'
export default defineComponent(() => {
const a = inject('a')
// ...
})
```### vModel
Similar to vue 3.
Support `` / `` / `` / ``
```jsx
import { defineComponent, ref, Input } from '@tybys/reactivuety'export default defineComponent(() => {
const inputValue = ref('')return () => () // <-- pass ref
/*
be equivalent to
return () => ( { inputValue.value = e.target.value }}
/>)
*/
})
```Also support modifiers: `vModel_lazy` / `vModel_number` / `vModel_trim`
```jsx
import { defineComponent, ref, Input } from '@tybys/reactivuety'export default defineComponent(() => {
const inputValue = ref('')return () => ()
/* return () => (
{ inputValue.value = e.target.value }}
/>
)
})
```### react compatible ref
```jsx
import { ref, onMounted, defineComponent } from '@tybys/reactivuety'
export default defineComponent(() => {
const a = ref(null)
onMounted(() => {
console.log(a.current) //reactivuety
})return () => (
reactivuety)
})
```## Note
* setup function is only called once, the first argument is readonly props `Proxy`
* setup function can return:
* object contains vue reactive object, all of them will be observed if accessed.
* render function without props, all accessed reactive objects in the render function will be observed.* lifecycle hooks should be called in setup function.
* `inject()` should be called in setup function.
* if `provide()` is called outside of setup function, it will provide your variable to root.
* the `onChange` event of `` and `` is native, not react's.