React-Vuera 0.2.5: :eyes: Vue in React, React in Vue. Seamless integration of the two. :dancers:

icon
Latest Release: 0.2.5

vuera

Build Status Coverage Status

NOTE: This project is looking for a maintainer!

Use Vue components in your React app:

import React from 'react'
import MyVueComponent from './MyVueComponent.vue'

export default props =>
  <div>
    <MyVueComponent message={props.message} handleReset={props.handleReset} />
  </div>

Or use React components in your Vue app:

<template>
  <div>
    <my-react-component :message="message" @reset="reset" />
  </div>
</template>

<script>
  import MyReactComponent from './MyReactComponent'

  export default {
    /* data, methods, etc */
    components: { 'my-react-component': MyReactComponent },
  }
</script>

Use cases

  • ?‍?‍? Using both Vue and React in one app
  • ? Migrating from React to Vue or from Vue to React

Installation

Install with yarn:

$ yarn add vuera
# or with npm:
$ npm i -S vuera

You can also try the library out via unpkg:

<script src="https://unpkg.com/vuera"></script>

Usage

Vue in React - Preferred usage

The preferred way to use Vue inside of a React app is to use a Babel plugin.

Add vuera/babel to plugins section of your .babelrc:

{
  "presets": "react",
  "plugins": ["vuera/babel"]
}

Now, just use your Vue components like you would use your React components!

import React from 'react'
import MyVueComponent from './MyVueComponent.vue'

export default () => (
  <div>
    <h1>I'm a react component</h1>
    <div>
      <MyVueComponent message='Hello from Vue!' />
    </div>
  </div>
)

React in Vue - Preferred usage

The preferred way to use React inside of a Vue app is to use a Vue plugin.

import Vue from 'vue'
import { VuePlugin } from 'vuera'

Vue.use(VuePlugin)
/* ... */

Now, use your React components like you would normally use your Vue components!

<template>
  <div>
    <h1>I'm a Vue component</h1>
    <my-react-component :message="message" @reset="reset" />
  </div>
</template>

<script>
  import MyReactComponent from './MyReactComponent'

  export default {
    data () {
      message: 'Hello from React!',
    },
    methods: {
      reset () {
        this.message = ''
      }
    },
    components: { 'my-react-component': MyReactComponent },
  }
</script>

If you configure options in the root instance of a Vue, those will not be passed by default to Vue instances within React components. So, for example an i18n or a store instance option configured at the top level is not available in the children Vue components wrapped in React components. To fix this, configure vueInstanceOptions similar to:

import Vue from 'vue'
// import other plugins or modules
import { config } from 'vuera'

// Vue.use(...)

config.vueInstanceOptions = { plugin: thePlugIn, store: myStore };

NOTE: If you're using Vue < 2.4, you must pass all props to your React components via a special prop called passedProps:

<template>
  <div>
    <h1>I'm a Vue component</h1>
    <my-react-component :passedProps="passedProps"></my-react-component>
  </div>
</template>

<script>
  import { ReactWrapper } from 'vuera'
  import MyReactComponent from './MyReactComponent'

  export default {
    data () {
      message: 'Hello from React!',
    },
    methods: {
      reset () {
        this.message = ''
      }
    },
    computed: {
      passedProps () {
        return {
          message: this.message,
          reset: this.reset,
        }
      },
    },
    components: { 'my-react-component': MyReactComponent },
  }
</script>

Vue in React - without the Babel plugin

If you don't want to use the Babel plugin, you still have two ways of using this library.

  1. Use a wrapper component:
import React from 'react'
import { VueWrapper } from 'vuera'
import MyVueComponent from './MyVueComponent.vue'

export default () => (
  <div>
    <VueWrapper
      component={MyVueComponent}
      message='Hello from Vue!'
    />
  </div>
)
  1. Or use the HOC API:
import React from 'react'
import { VueInReact } from 'vuera'
import MyVueComponent from './MyVueComponent.vue'

export default () => {
  const Component = VueInReact(MyVueComponent)
  return (
    <div>
      <Component message='Hello from Vue!' />
    </div>
  )
}

React in Vue - without the Vue plugin

If you don't want to use the Vue plugin, you still have two ways of using this library.

  1. Use a wrapper component:
<template>
  <div>
    <react :component="component" :message="message" />
  </div>
</template>

<script>
  import { ReactWrapper } from 'vuera'
  import MyReactComponent from './MyReactComponent'

  export default {
    data () {
      component: MyReactComponent,
      message: 'Hello from React!',
    },
    components: { react: ReactWrapper }
  }
</script>
  1. Use the HOC API:
<template>
  <div>
    <my-react-component :message="message" />
  </div>
</template>

<script>
  import { ReactInVue } from 'vuera'
  import MyReactComponent from './MyReactComponent'

  export default {
    data () {
      message: 'Hello from React!',
    },
    components: { 'my-react-component': ReactInVue(MyReactComponent) }
  }
</script>

FAQ (I think)

Are children supported?

Yes. You can pass children from React to Vue and back as you usually would.

React (children will go to the default slot of the Vue component):

import React from 'react'
import MyVueComponent from './MyVueComponent.vue'

export default props =>
  <div>
    <MyVueComponent message={props.message}>
      Hello there!
    </MyVueComponent>
  </div>

Vue:

<template>
  <div>
    <my-react-component :message="message">
      G'day sir
    </my-react-component>
  </div>
</template>

<script>
  import MyReactComponent from './MyReactComponent'

  export default {
    components: { 'my-react-component': MyReactComponent },
  }
</script>

What's the performance? How fast/slow is it compared to pure React / Vue?

I don't know, but the benchmark is coming. Stay tuned.

Articles

Integrating React and Vue Components in One Application by @josephrexme

License

MIT

Comments

  • Cant support className when use React Component in Vue
    Cant support className when use React Component in Vue

    Sep 28, 2021

    When I wrote a react component index.jsx

    export const SupportCard = (props) => {
        const { data = [] } = props.props.attrs
        return (<div class="support-cards">
            {data.map((v, i) => {
                return <a className="support-card-item" href={v.href} key={i}>
                    <img className="support-card-img" src={v.src} alt="" />
                    <div className="support-card-content">
                        <div className="support-card-title">{v.title || ''} 〉</div>
                        <div className="support-card-desc">{v.desc || ''}</div>
                    </div>
                </a>
            })}
        </div>)
    }
    

    And use in Vue web.vue

    <template>
      <node-view-wrapper>
        <component-wraper :attrs="node.attrs" :updateAttributes="updateAttributes">
          <support-card :attrs="node.attrs" />
        </component-wraper>
      </node-view-wrapper>
    </template>
    
    <script>
    import { NodeViewWrapper, nodeViewProps } from '@tiptap/vue-2'
    import { SupportCard } from './index.jsx'
    import { ComponentWraper } from '../common/WraperEditor'
    
    export default {
      props: nodeViewProps,
    
      components: {
        'support-card': SupportCard,
        'component-wraper': ComponentWraper,
        NodeViewWrapper,
      },
    }
    </script>
    
    <style lang="scss">
    .support-cards {
      display: flex;
      justify-content: center;
      text-align: center;
      align-items: center;
      pointer-events: none;
    
      .support-card-item {
        flex: 1;
    
        .support-card-img {
          widows: 80px;
          height: 80px;
          margin: 10px;
        }
    
        .support-card-title {
          text-align: center;
        }
      }
    }
    </style>
    

    The style cant word.

    I need change className to class in index.jsx , the style will be fine.

    export const SupportCard = (props) => {
        const { data = [] } = props.props.attrs
        return (<div class="support-cards">
            {data.map((v, i) => {
                return <a class="support-card-item" href={v.href} key={i}>
                    <img class="support-card-img" src={v.src} alt="" />
                    <div class="support-card-content">
                        <div class="support-card-title">{v.title || ''} 〉</div>
                        <div class="support-card-desc">{v.desc || ''}</div>
                    </div>
                </a>
            })}
        </div>)
    }
    
    Reply
  • complex
    complex

    Oct 21, 2021

    In the vue project, if my React component has a strong dependency on redux and some middleware, it cannot be split. According to the method in the document, I got a lot of errors that are basically dependent problems, as well as jsx problems. Is there any other better way to achieve this in this situation?

    Reply
  • Creates an extra div around React components
    Creates an extra div around React components

    Oct 26, 2021

    Each time I try and render a react component inside my vue component, there is an extra div wrapped around my react component. I'm not sure if there is a way to change that element or even just remove it, and I did not see any options in the README to do so. The problem is that any components designed to be inline such as buttons or inputs or links are totally useless. I suggest at the very least changing the wrapping tag to a span, making it configurable, or if possible, git rid of it?

    relates to https://github.com/akxcv/vuera/issues/19

    Reply
  • fix this stupid line
    fix this stupid line

    Nov 30, 2021

    This line was causing an error for me.

    I don't know why, but editing this fixes it

    Reply
  • support vue3 in react17 project?
    support vue3 in react17 project?

    Dec 10, 2021

    null

                                                                                                                                                                                                           
    Reply
  • TypeScript support
    TypeScript support

    Dec 11, 2021

    Supporting Typescript in Vuera

    Reply
  • Events
    Events

    Aug 9, 2018

    Vue in React, how would 1 handle events from a vue component vm.$emit('eventnnaeme', stuff)

    help wanted good first issue 
    Reply
  • Unknown custom element router-view
    Unknown custom element router-view

    Oct 18, 2017

    I have Vuera loaded in the same file as my vue router but when I mount vuera it affects vue-router. Here's my router file:

    import Vue from 'vue'
    import Router from 'vue-router'
    import { VuePlugin } from 'vuera'
    import Home from '@/components/Home'
    
    Vue.use(VuePlugin)
    Vue.use(Router)
    
    export default new Router({
      routes: [
        {
          path: '/',
          name: 'Home',
          component: Home
        }
      ]
    })
    

    when I take out the 3rd and 6th line with Vuera/VuePlugin, the app works again. Here's the error I get:

    Unknown custom element: <router-view>
    
    bug help wanted 
    Reply
  • [Fix] Component prop updates, issues with children
    [Fix] Component prop updates, issues with children

    Oct 7, 2017

    Fixes #8.

    I will add tests later. I would be very grateful if you reviewed the changes in src/wrappers/Vue.js and src/wrappers/React.js.

    The changes in React wrapper are pretty straightforward, but the changes in the Vue wrapper are a bit weird and hacky. Please don't hesitate to point out any ways of improvement.

    Also, I would be very grateful for any comments and corrections on the inline documentation in those files. Tell me if some comments need clarification.

    Reply
  • Fix babel plugin import
    Fix babel plugin import

    Oct 4, 2017

    fixes #5 Also added a changelog.

    Reply
  • How to use Vue event handlers in React?
    How to use Vue event handlers in React?

    Oct 12, 2017

    In Vue, we can use v-on:click directive, and in React it can be onClick. If I want to embed Vue components in React, how can I bind click event to them?

    question 
    Reply
  • Project built with Vue TS component fails
    Project built with Vue TS component fails

    Jul 6, 2018

    I was using Vuetify components, but recently they updated them to support TS. My build completes, but website breaks with an error: image Project (Vue based) bricks like this while using any component from Vuetify (not a single React component included). I think that Vuera is trying to do something with Vue TS components, because it thinks that it's React component.

    Reply