Gathering detailed insights and metrics for @empathyco/x-react-wrapper
Gathering detailed insights and metrics for @empathyco/x-react-wrapper
Gathering detailed insights and metrics for @empathyco/x-react-wrapper
Gathering detailed insights and metrics for @empathyco/x-react-wrapper
Commerce Search & Discovery frontend web components
npm install @empathyco/x-react-wrapper
Typescript
Module System
Min. Node Version
Node Version
NPM Version
TypeScript (65.28%)
Vue (26.4%)
HTML (5.61%)
Gherkin (1.92%)
JavaScript (0.61%)
SCSS (0.17%)
CSS (0.01%)
Total Downloads
0
Last Day
0
Last Week
0
Last Month
0
Last Year
0
Apache-2.0 License
83 Stars
2,728 Commits
22 Forks
21 Watchers
207 Branches
137 Contributors
Updated on Jul 09, 2025
Latest Version
4.1.2-alpha.0
Package Id
@empathyco/x-react-wrapper@4.1.2-alpha.0
Unpacked Size
38.61 kB
Size
11.23 kB
File Count
15
NPM Version
lerna/6.6.0/node@v18.18.2+x64 (linux)
Node Version
18.18.2
Published on
Nov 29, 2023
Cumulative downloads
Total Downloads
Last Day
0%
NaN
Compared to previous day
Last Week
0%
NaN
Compared to previous week
Last Month
0%
NaN
Compared to previous month
Last Year
0%
NaN
Compared to previous year
1
React wrapper is a library that allows to use Vue components inside a React project. It tries to provide the same APIs that Vue has, but in a React way: props, events, slots, scoped slots...
To start using this library, simply add it to your React project dependencies, together with
react
, react-dom
, and vue
:
# or pnpm or yarn
npm install @empathyco/react-wrapper react react-dom vue
After installing these dependencies, you can start using the ReactWrapper
. To do so, you just have
to use it like a normal React component, the only required prop is the component
one, which must
be passed with the Vue component to render.
1// File hello-world.vue 2<template> 3 <h1>Hello world!</h1> 4</template>
1// File App.ts 2import { ReactWrapper } from '@empathco/react-wrapper'; 3import HelloWorld from './hello-world.vue'; 4import React from 'react'; 5 6function App() { 7 return ( 8 <main> 9 <ReactWrapper component={HelloWorld} /> 10 </main> 11 ); 12}
To pass some props to the Vue component rendered by ReactWrapper
, just pass them as you would with
a normal React component. ReactWrapper
will forward them to the Vue component:
1// File message.vue 2<template> 3 <h1>{{ message }}</h1> 4</template> 5<script> 6 export default { 7 props: ['message'] 8 }; 9</script>
1// File App.tsx 2import { ReactWrapper } from '@empathyco/react-wrapper'; 3import Message from './message.vue'; 4import React from 'react'; 5 6function App() { 7 return ( 8 <main> 9 <ReactWrapper component={Message} message={'Hello World!'} /> 10 </main> 11 ); 12}
Note that there are some special properties that shouldn't be used. The on
, children
and slots
props are used to expose other Vue APIs. This is explained in the events
and children & slots sections.
While React treats events callbacks as normal props, Vue makes a distinction between them and the
normal ones. That's why, to use events in the ReactWrapper
you have to use a special prop called
on
. This prop is just a dictionary of events callbacks, where the key is the event name, and the
value is the callback itself, which can have a payload associated.
1// File button.vue 2<template> 3 <button @click="emitClick">Click me!</button> 4</template> 5<script> 6 export default { 7 methods: { 8 emitClick() { 9 this.$emit('click:button', 'Button was clicked'); 10 } 11 } 12 }; 13</script>
1// File App.tsx 2import { ReactWrapper } from '@empathyco/react-wrapper'; 3import Button from './button.vue'; 4import React from 'react'; 5 6function App() { 7 return ( 8 <main> 9 <ReactWrapper 10 component={Button} 11 on={{ 'click:button': payload => console.log('Click', payload) }} 12 /> 13 </main> 14 ); 15}
Vue has an advanced API for handling the children of elements. Apart from the traditional default slot which allows you to pass some children to a component, it provides a way for creating named and scoped slots. Named slots allows passing children to different part of a component, while scoped slots provides a way for raising data to the component that provides the slots.
To use default slots there are 3 ways: nesting the children inside the component, or using the
children
& slots.default
props.
1// File title.vue 2<template> 3 <h1><slot /></h1> 4</template> 5<script> 6 export default {}; 7</script>
1// File App.tsx 2import { ReactWrapper } from '@empathyco/react-wrapper'; 3import Title from './title.vue'; 4import React from 'react'; 5 6function App() { 7 return ( 8 <main> 9 <ReactWrapper component={Button}> 10 Hello <strong>World</strong> 11 </ReactWrapper> 12 </main> 13 ); 14}
1// File App.tsx 2import { ReactWrapper } from '@empathyco/react-wrapper'; 3import Title from './title.vue'; 4import React from 'react'; 5 6function App() { 7 return ( 8 <main> 9 <ReactWrapper 10 component={Title} 11 slots={{ 12 default: ['Hello', <strong>World</strong>] 13 }} 14 /> 15 </main> 16 ); 17}
1// File article-preview.vue 2<template> 3 <article> 4 <h1>{{ article.title }}</h1> 5 <span><slot name="author" :author="author" /></span> 6 <div>{{ article.body }}</div> 7 <slot name="extra" /> 8 </article> 9</template> 10<script> 11 export default { 12 props: ['article'], 13 computed: { 14 author() { 15 return article.author || 'Anonymous'; 16 } 17 } 18 }; 19</script>
1// File App.tsx 2import { ReactWrapper } from '@empathyco/react-wrapper'; 3import ArticlePreview from './article-preview.vue'; 4import React from 'react'; 5 6const article = { 7 title: 'Vue slots API', 8 body: 'A short guide about how to use vue slots.' 9}; 10 11function App() { 12 return ( 13 <main> 14 <ReactWrapper 15 component={ArticlePreview} 16 article={article} 17 slots={{ 18 author: computedAuthor => <strong>computedAuthor</strong>, 19 extra: <a href='#'>Read more</a> 20 }} 21 /> 22 </main> 23 ); 24}
ReactWrapper
works by creating an internal Vue instance that is mounted inside the ReactWrapper
component. Vue rendered content is inserted inside the div
element rendered by the ReactWrapper,
taking control of the DOM tree from that part.
Proxying APIs is the "easy" part of this library. React flexibility helps when exposing Vue APIs
like events or slots. ReactWrapper
only has to sync the props received with its internal Vue
instance ones. Whenever the props change, it extracts them again, and notifies the Vue instance
about them.
The biggest challenge of this library is the DOM reconciliation. As the DOM is handled by both Vue
and React, they expect to have full control of it, and if one library makes a change to the DOM.
But, because ReactWrapper
renders a div
, and Vue content is inserted inside it, there are no
problems. React has control of the app until this div
, and Vue from that point.
On the other hand, slots are a bit more complex. Slots work by using a special Vue component,
VueChildrenWrapper
. This component renders a div
, and receives React virtual nodes as props.
When the VueChildrenWrapper
component is mounted, it renders the React nodes inside it. Just like
the ReactWrapper
does with the children nodes.
The problematic part here is unmounting a component which has animations. When the Vue component is
destroyed, the React one should be destroyed too. The challenge is that Vue fires beforeDestroy
and destroyed
hooks before the component is removed from the DOM, and then it runs the leaving
animations if it has. So the solution is to observe the nodes with a MutationObserver
. If the
nodes are detached, then it is safe to unmount the React component too.
No vulnerabilities found.
Reason
no dangerous workflow patterns detected
Reason
security policy file detected
Details
Reason
30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
Reason
no binaries found in the repo
Reason
license file detected
Details
Reason
SAST tool is run on all commits
Details
Reason
dependency not pinned by hash detected -- score normalized to 7
Details
Reason
Found 10/21 approved changesets -- score normalized to 4
Reason
branch protection is not maximal on development and all release branches
Details
Reason
detected GitHub workflow tokens with excessive permissions
Details
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
project is not fuzzed
Details
Reason
21 existing vulnerabilities detected
Details
Score
Last Scanned on 2025-07-07
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More