import React, { useEffect, useRef } from 'react'; | |
import ReactDOM from 'react-dom'; | |
import { defineComponent, onMounted, onUnmounted } from '@vue/composition-api'; | |
import Vue from 'vue'; | |
export function vuenize(component: React.ComponentType, parentData: Vue.VNodeData = {}) { | |
const randomKey = 'key_' + Math.random(); | |
let mountedNode: any = null; | |
return defineComponent({ | |
name: component.name || component.displayName, | |
render(h) { | |
return h('div', { class: randomKey, ...parentData }); | |
}, | |
setup(props: any) { | |
onMounted(() => { | |
mountedNode = document.getElementsByClassName(randomKey)[0]; | |
if (mountedNode) { | |
ReactDOM.render(React.createElement(component, props), mountedNode); | |
} | |
}); | |
onUnmounted(() => { | |
if (mountedNode) ReactDOM.unmountComponentAtNode(mountedNode); | |
}); | |
return {}; | |
}, | |
}); | |
} | |
export function reactnize(component: any, parentProps: any) { | |
return (props: any) => { | |
const ref = useRef<HTMLDivElement>(null); | |
useEffect(() => { | |
if (ref.current == null) return; | |
const App = Vue.extend(component); | |
const vm = new App({ | |
el: ref.current, | |
props, | |
}); | |
return () => vm.$destroy(); | |
}, [ref.current, props]); | |
return React.createElement( | |
'div', | |
{ | |
...parentProps, | |
}, | |
React.createElement('div', { ref }), | |
); | |
}; | |
} | |
/* How to use | |
import React from "react"; | |
import {vuenize, reactnize} | |
function Foo() { | |
return <div>foo</div> | |
} | |
export default { | |
components: { | |
Foo: vuenize(Foo) | |
} | |
} | |
import ReactDOM from "react-dom"; | |
import Bar from "./Bar.vue" | |
const ReactBar = reactnize(Bar); | |
ReactDOM.render(<ReactBar />) | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment