Coder Social home page Coder Social logo

akxcv / vuera Goto Github PK

View Code? Open in Web Editor NEW
4.3K 48.0 240.0 367 KB

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

License: MIT License

JavaScript 100.00%
vue react interop migrate seamless-integration vue-plugin babel-plugin

vuera's Introduction

vuera

Build Status Coverage Status

โš ๏ธ Vuera has been archived.

Check out veaury or vuera-ts for a more up-to date library.

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

vuera's People

Contributors

akxcv avatar fsodano avatar khashish avatar nhducit avatar phillbaker avatar runebaas avatar walts81 avatar wenlz123 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

vuera's Issues

Didn't work at all with React components library

Hello there! I am trying to use VKUI React-library in my Vue application.

Here is my App.vue:

<template>
  <VKView id="main" activePanel="panel">
    <Panel id="panel">
      test
    </Panel>
  </VKView>
</template>

<script>

import {View, Panel} from "@vkontakte/vkui";

export default {
  name: 'app',
  components: {
    "VKView": View,
    "Panel": Panel
  }
}
</script>

And this is my main.js:

import Vue from 'vue'
import App from './App.vue'

import { VuePlugin } from 'vuera';
Vue.use(VuePlugin);

import '@vkontakte/vkui/dist/vkui.css';

new Vue({
  render: h => h(App)
}).$mount('#app')

Everything builds and runs without errors, but result DOM tree have no children in each component, so I just got empty white page:

<section class="View View--ios View--header">
  <div class="View__header">
    <div class="View__header-scrolltop"></div>
    <div class="PanelHeader PanelHeader--ios"></div>
  </div>
  <div class="View__panels"></div>
</section>

And this is how it should look:

<section class="View View--ios View--header" id="main">
  <div class="View__header">
    <div class="View__header-scrolltop"></div>
    <div class="PanelHeader PanelHeader--ios">
      <div class="PanelHeader__in PanelHeader__in--active">
        <div id="header-bg-panel" class="PanelHeader__bg"><!----></div>
        <div class="PanelHeader__container">
          <div class="PanelHeader__left">
            <div id="header-left-panel" class="PanelHeader__left-in"><!----></div>
            <div id="header-addon-panel" class="PanelHeader__addon"><!----></div>
          </div>
          <div id="header-title-panel" class="PanelHeader__content"><!----></div>
          <div id="header-right-panel" class="PanelHeader__right"><!----></div>
        </div>
      </div>
    </div>
  </div>
  <div class="View__panels">
    <div class="View__panel View__panel--active">
      <div class="View__panel-in">
        <div id="panel" class="Panel Panel--ios Panel--tm-gray">
          <div class="Panel__in">
            <div class="Panel__in-before"></div>
              test
            <div class="Panel__in-after"></div>
          </div>
        </div>
      </div>
    </div>
  </div>
</section>

Too many div generation from using ReactWrapper

After #18 failed with the VuePlugin I tried to do the same with the alternative ReactWrapper and though the following code works,

<template>
  <div class="hello">
    <react :component="grid">
      <react :component="gridcol">2</react>
      <react :component="gridcol">2</react>
    </react>
  </div>
</template>

<script>
import ScrollIndicator from '@/components/ScrollIndicator.vue'
import { ReactWrapper } from 'vuera'
import { Grid, GridCol } from 'griz'

export default {
  name: 'home',
  data() {
    return {
      msg: 'Test data',
      grid: Grid,
      gridcol: GridCol,
    }
  },
  components: { ScrollIndicator, react: ReactWrapper }
}
</script>

In a React application grid will be a flex container and grid-col its flex items. The problem here is each of them are rendered with extra divs inside of them which breaks the flex layout.

I get:

gridComponentWrapper
   |--grid
           |-- div
                  |-- gridcolComponentWrapper
                           |-- gridcol
                                  |-- div
                                         |-- 2
                  |-- gridcolComponentWrapper
                           |-- gridcol
                                  |-- div
                                         |-- 2

where I expected

grid
  |-- gridcol
          |-- 2
  |-- gridcol
          |-- 2

Juggle the tagline, to make it rhyme

I had to read it a couple of times,
and was sad to hear it didn't rhyme.

Would suggest you make it something like this,
and live in a world of poetic bliss

Vue in React, React in Vue.
A seamless integration, of the two.

๐Ÿ˜

Context API support

I'm attempting to utilize Vuera to create Gutenberg components for Wordpress using Vue. Overall I'm pretty happy with it, but I'm running into a limitation that severely restricts the set of things I can do:

Gutenberg utilizes the Context API that was introduced in React 16 extensively throughout its built-in editor components, particularly to manage when a block is "selected" vs not. This context does not appear to bridge across the vuera embed.

The high level structure I'm using returns a VueInReact wrapped component to Gutenberg, with my core Vue component handling my custom logic, and then as necessary embedding ReactInVue wrapped Gutenberg builtins.

So we have
React (gutenberg, sets context)
-> Vue (my code)
----> React (gutenberg, looks for context and doesn't find it)

I'm happy to try to figure out/implement a fix for this, but would appreciate a pointer in the right direction if you have any ideas.

Can't use React component (react-grid-layout) in Vue

Hi,

I'm trying to use react-grid-layout in Vue using your awesome library. Here is what I have:

// Grid.vue
<template>
  <GridLayout className="layout" :cols="12" :rowHeight="30" :width="1200">
    <div key="a" :data-grid="{x: 0, y: 0, w: 1, h: 2, static: true}">a</div>
    <div key="b" :data-grid="{x: 1, y: 0, w: 3, h: 2, minW: 2, maxW: 4}">b</div>
    <div key="c" :data-grid="{x: 4, y: 0, w: 1, h: 2}">c</div>
  </GridLayout>
</template>

<script lang="ts">
// @ts-ignore
import GridLayout from 'react-grid-layout';

export default {
  name : 'Grid',
  components: { GridLayout },
};
</script>
<style>
@import '/node_modules/react-grid-layout/css/styles.css';
@import '/node_modules/react-resizable/css/styles.css';
</style>
// App.vue
<template>
  <div id="app">
    <Grid/>
  </div>
</template>

<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
// @ts-ignore
import Grid from './components/Grid.vue';

@Component({
  components: {
    Grid,
  },
})

export default class App extends Vue {}

</script>

As you can see I'm using GridLayout component from react and wrapping it into Vue component (Grid). First of all, am I doing this correctly? Grid component doesn't get displayed at all, but I don't see any errors in yarn serve output. I can see <react-wrapper> under <GridLayout in Vue's DOM (with Vue-devtools). I've tried doing it as in issue 26, but still no success. Do you know how to fix this?

My dependencies:

"dependencies": {
    "react": "^16.4.1",
    "react-dom": "^16.4.1",
    "react-grid-layout": "^0.16.6",
    "vue": "^2.5.16",
    "vue-class-component": "^6.0.0",
    "vue-grid-layout": "^2.1.13",
    "vue-property-decorator": "^6.0.0",
    "vuera": "^0.2.2"
  },

Thanks!

Parse error using vue in react

Bug Report

Describe the bug

After including 'vuera/babel' in babel-loader plugins it start giving some errors in react parse.
Is there any exception in vue or vue-loader version for support ?

Thanks!

Console error:

Uncaught TypeError: Cannot read property 'constructor' of undefined
    at isReactComponent (vuera.cjs.js?ea64:410)
    at babelReactResolver$$1 (vuera.cjs.js?ea64:475)
    at ProxyComponent.render (root.jsx?1914:29)
    at ProxyComponent.hotComponentRender (react-hot-loader.development.js?ba54:622)
    at ProxyComponent.proxiedRender (react-hot-loader.development.js?ba54:630)
    at finishClassComponent (react-dom.development.js?61bb:13193)
    at updateClassComponent (react-dom.development.js?61bb:13155)
    at beginWork (react-dom.development.js?61bb:13824)
    at performUnitOfWork (react-dom.development.js?61bb:15863)
    at workLoop (react-dom.development.js?61bb:15902)

The above error occurred in the <Root> component:
    in Root
    in AppContainer
    in HotExportedRoot

React will try to recreate this component tree from scratch using the error boundary you provided, AppContainer.

Code reference
doczjs/docz#50

Environment

  • Node/npm version: Node v9.11.2/npm 6.0.0

Error calling React from Vue ("h is not a function")

I'm having issues calling a React component from a freshly generated Vue project and must be doing something wrong.

So, starting with vue --version at 2.9.3 (the latest released version) and accepting the defaults in the vue-cli script.

vue init webpack myapp
cd myapp
yarn add vuera react react-dom

Now, I modified the generated /src/main.js entrypoint to import and use the VuePlugin from vuera:

import Vue from 'vue'
import App from './App'
import { VuePlugin } from 'vuera'

Vue.config.productionTip = false

Vue.use(VuePlugin)

/* eslint-disable no-new */
new Vue({
  el: '#app',
  components: { App },
  template: '<App/>'
})

Modified the generated App.vue to import and attempt to use the React component:

<template>
  <div id="app">
    <img src="./assets/logo.png">
    <HelloWorld/>
    <react-component message="Hello"></react-component>
  </div>
</template>

<script>
/* eslint-disable */
import HelloWorld from "./components/HelloWorld";
import ReactComponent from "./components/ReactComponent";

export default {
  name: "App",
  components: {
    HelloWorld,
    "react-component": ReactComponent
  }
};
</script>

<style>
#app {
  font-family: "Avenir", Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

Finally added the simple React component /components/ReactComponent.js:

import React from 'react'

export default class ReactComponent extends React.Component {
  render() {
    return (
      <div>
        <p>This was rendered with React!</p>
        <p>{this.props.message}</p>
      </div>
    )
  }
}

Webpack compiles everything fine, but when requesting http://localhost:8080 my React component is not rendered under the "Hello World" Vue component. Instead I get 4 errors in the console starting with "Uncaught TypeError: h is not a function".

screen shot 2018-03-05 at 9 31 07 am

I also tried using the ReactWrapper but had the same result.

I'm at the latest vuera 0.2.1, vue 2.5.13, react & react-dom 16.2.0, webpack 3.11.0.

This library looks to be awesome once it's working, thanks for any help!

Empty window in React

When I add "vuera/babel" to project, React renders empty page without errors.

  "babel": {
    "plugins": [
      "babel-plugin-transform-decorators-legacy",
      "vuera/babel"
    ],
    "presets": [
      "react-app"
    ]
  },

babel-plugin-transform-decorators-legacy needed for Mobx

Unknown custom element router-view

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>

Usage with webpack error.

Uncaught Error: Module build failed: ReferenceError: Unknown plugin "vuera/babel" specified in "base" at 1, attempted to resolve relative to "C:\Users\skrrt\Desktop\stuff\ttn-front\src".

Tried everything to work with babel-loader through webpack, can't get it to work.

More like a general question, how to set up with webpack?

Event handling issue: Vue app and own React component

Hello. Thanks for the vuera.

I have a Vue application, and I use third party React components from other team, and from MUI library.

There is a Switch component in form, here is an example of usage:

<FormControlLabel
    control={
        <Switch
            checked={this.state.checkedA}
            onChange={this.handleChange('checkedA')}
            value="checkedA"
        />
    }
    label="Secondary"
/>

As far as understand - I can't pass a component as a property, so I have made a wrapped Switch component.

import React from 'react';
import { Switch, FormControlLabel } from 'material-ui';

class WrappedSwitch extends React.Component {
    render() {
        return (<FormControlLabel
            control={
                <Switch
                    checked={this.props.isChecked}
                    onChange={this.props.onChange}
                    value={this.props.value}
                />
            }
            label={this.props.labelText}
        />);
    }
}

export default WrappedSwitch;

Component is being rendered fine, but onChange event doesn't fire.

In Vue component:

WrappedSwitch(
    :isChecked="form.isAvail",
    @onChange="handleAvailabilityChange",
    value="isAvailable",
    labelText="Is available",
)

What can be done wrong?

Thanks a lot.

Rewrite tests to run native ES6

Currently, all test and library code gets transpiled to ES5 before running. This may cause issues as we don't properly test vuera's behaviour on ES6.

Using Orb.js in Vue?

Hello. I'm trying to use the Orb.js component in Vue.
I installed vuera, react, and Orb with npm
Then I added vuera in the app's index.js:

import Vue from 'vue';
import { VuePlugin } from 'vuera'
Vue.use(VuePlugin)

At the top of my component's <script> tag:

import orb from "orb"

Then added to my component's exports:

components: { 'orb': Orb },

But when I run this, I get:

orb.react.compiled.js?1fcc:27 Uncaught TypeError: Cannot read property 'createClass' of undefined
    at eval (orb.react.compiled.js?1fcc:27)
    at Object../node_modules/orb/src/js/react/orb.react.compiled.js (app.js:3748)
    at __webpack_require__ (app.js:679)
    at fn (app.js:89)
    at eval (orb.ui.pgridwidget.js?b892:17)
    at Object../node_modules/orb/src/js/orb.ui.pgridwidget.js (app.js:3725)
    at __webpack_require__ (app.js:679)
    at fn (app.js:89)
    at eval (orb.js?0913:31)
    at Object../node_modules/orb/src/js/orb.js (app.js:3661)

this happens because "react" is not defined. Am I missing something?

Commendation

Hello, I want to praise this. Although I haven't used it yet. I was really excited that someone decided to bridge the gap between Vue and React. Well done ๐Ÿ‘ I'd be happy to contribute too.
P.S. apologies for putting this in issues

TypeError: Cannot call a class as a function

I am getting this error when I import my react component in Vue component

vue.esm.js?a026:1841 TypeError: Cannot call a class as a function
    at _classCallCheck (classCallCheck.js?d225:3)
    at CalendarWithData (CalenderMetaData.jsx?ee20:89)
    at resolveAsyncComponent (vue.esm.js?a026:2461)
    at createComponent (vue.esm.js?a026:4330)
    at _createElement (vue.esm.js?a026:4546)
    at createElement (vue.esm.js?a026:4483)
    at vm._c (vue.esm.js?a026:4615)
    at Proxy.render (eval at ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"690fb1ea-vue-loader-template"}!./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/components/Calendar/Calendar.vue?vue&type=template&id=89a25360& (24.bc8344237482e96f14d3.hot-update.js:23), <anonymous>:638:17)
    at VueComponent.Vue._render (vue.esm.js?a026:4662)
    at VueComponent.updateComponent (vue.esm.js?a026:2908)

Standard usage not working

I'm trying to use Vue in React using the standard usage but it's returning the following error message. It seems like Babel still expects the .vue files to be valid JSX.

It's worth noting that I'm also very new to react, webpack, and everything.

The error:

Module build failed: SyntaxError: Adjacent JSX elements must be wrapped in an enclosing tag (5:0)

  3 | </template>
  4 | 
> 5 | <script>
    | ^
  6 | export default {
  7 | 	data () {
  8 | 		return {

BabelLoaderError: SyntaxError: Adjacent JSX elements must be wrapped in an enclosing tag (5:0)

  3 | </template>
  4 | 
> 5 | <script>
    | ^
  6 | export default {
  7 | 	data () {
  8 | 		return {

My babel.rc:

{
   "presets":["es2015", "react", "stage-0"],
   "plugins": ["vuera/babel"]
}

My webpack.config.js:

{
const path = require('path');
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');

var plugins = [
  new ExtractTextPlugin('[name]', {
      allChunks: true
  })
]

if (process.env.NODE_ENV == "production") {
  plugins.push(
    new webpack.DefinePlugin({
      'process.env': {
        'NODE_ENV': JSON.stringify('production')
      }
    }),
    new webpack.optimize.UglifyJsPlugin({
        compress: {
            warnings: false
        }
    })
  )
}

//create entries
var pages = [
  'index',
]

var entries = {}
for (var i = 0; i < pages.length; i++){
  var fileName = pages[i]

  entries['js/' + fileName + '.js'] = path.resolve(__dirname, 'main', 'static', 'js', 'pages', fileName + '.jsx')
  entries['css/' + fileName + '.css'] = path.resolve(__dirname, 'main', 'static', 'sass', fileName + '.scss')
}

const compiler = {
  entry: entries,
  resolve: {
    alias: {
      components: path.resolve(__dirname, 'main', 'static', 'js', 'components'),
      utilities: path.resolve(__dirname, 'main', 'static', 'js', 'utilities'),
      images: path.resolve(__dirname, 'main', 'static', 'images'),
      sass: path.resolve(__dirname, 'main', 'static', 'sass'),
    },
    extensions: ['', '.js', '.jsx', '.png', '.jpg', '.svg'],
  },
  module: {
    loaders: [
      {
        exclude: /node_modules/,
        loader: 'babel',
        test: /\.(jsx|js|vue)$/,
      },
      {
        test: /\.module\.scss$/,
        loader: 'style!css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!sass',
        //loader: ExtractTextPlugin.extract('css?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]'),
      },
      {
          test: /^((?!\.module).)*\.scss$/,
          loader: ExtractTextPlugin.extract('css!sass')
      },
      {
        test: /\.(png|jpg|svg)$/,
        loader: 'url-loader',
      },
    ],
  },
  output: {
    path: "./main/static/dist",
    filename: "[name]",
  },
  plugins: plugins
};

module.exports = compiler;

}

ReactDOM.createPortal instead of ReactDOM.render

Did you already try the new ReactDOM.createPortal as replacement for ReactDOM.render?

The benefits would be to have only 1 react app for all ReactInVue components (instead of N reacts apps, one for each ReactInVue component). Also one would be able to define a single react context to be used by all ReactInVue components. Maybe this will have some (positive) impact on your planned Benchmark #16?

AngularJS with Vue

With vue-class-component

Like this:

import { NoCache } from './decorators'

@Component
class MyComp extends Vue {
  // the computed property will not be cached
  @NoCache
  get random () {
    return Math.random()
  }
}

AngularJS With decorators

Maybe like this:

import { Inject, Mixin, Observable, Component } from 'angular-onion'

import auto from './mixin.js'
import justTestHtml from './just-test.html'

@Component({
    selector: 'just-test',
    props: {
        type: '@'
    },
    template: justTestHtml
})

@Inject('Validators')

@Mixin(auto)
class justTestController {
    constructor () {
       // constructor
       this.user = 'onion'
    }

    @Observable(() => this.user, true)
    watchUser (newVal) {
       // Observable callback
    }

    $onInit () {
       // lifecycle
    }

    ....
}

Use Vue components in AngularJS, use AngularJS components in Vue.
Is there a way?

HOC API?

It would be nice

const ReactComponent = VueToReact(VueComponent)
// or
const VueComponent = ReactToVue(ReactComponent)

Component requires setState property, how to call it?

I'm trying to use react-pivottable (https://github.com/plotly/react-pivottable). I have it running in my project, with live data. Except it doesn't update whenever I drag columns. This seems to happen because in React it's supposed to be initialized like this:

import React from 'react';
import PivotTableUI from 'react-pivottable/PivotTableUI';
import 'react-pivottable/pivottable.css';

// see documentation for supported input formats
const data = [['attribute', 'attribute2'], ['value1', 'value2']];

class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = props;
    }

    render() {
        return (
            <PivotTableUI
                data={data}
                onChange={s => this.setState(s)}
                {...this.state}
            />
        );
    }
}

ReactDOM.render(<App />, document.body);

Because as the docs say: "Note that PivotTableUI is a "dumb component" that maintains essentially no state of its own."

I'm using the component in my project like this

<PivotTableUI className="resizable-item" :data="data"  ></PivotTableUI>

And of course, I get:

warning.js?6327:33 Warning: Failed prop type: The prop `onChange` is marked as required in `PivotTableUI`, but its value is `undefined`.
    in PivotTableUI (created by ReactInVuePivotTableUI)
    in ReactInVuePivotTableUI

I'm not quite sure how I should be handling this event...

Benchmark

I'm eager to optimise this library, to make it perform as fast as possible, and I already have some thoughts about how to do that. Before optimising anything, though, it's necessary to have a benchmark of the library.

I've been thinking of forking js-framework-benchmark and adding some benchmarks for vuera to the fork.

I'm not sure, though, what exactly we should measure, and I don't know when I'll find the time to do this, so if anyone wishes to help, this is very appreciated.

Usage with Vuex

Is there any way to maintain the $store Vuex instance property that's provided by Vuex? My app is a Vue application that uses Vuex for state management, but after reaching a React component that has Vue components as children, those components no longer have access to the Vuex store.

Outside of that I'm loving it so far, very easy to integrate with presentational components that don't need access to state, I'm just running into this issue on components requiring access to global state. :)

how to use react component in vue with object`s values

hello, i have a problem with this project. here`s my code

blockRendererFn (contentBlock) {
      const type = contentBlock.getType()
      let result = null
      if (type === 'atomic') {
        result = {
          component: Test,
          editable: false
        }
      }
      return result
    }

as you can see, i need pass a react component to a obj. like Test
here is Test code

// test.js
import React from 'react';

export default function Test () {
  return (<span>hello</span>)
}

but it does not work.
if Test function return a string, it work well, but its not what i expected
i hope return a component, please help me
thanks

vue transition warning

When I use React in vue it works but have a waning with vue

[Vue warn]: Unknown custom element:
<transition> - did you register the component correctly? For recursive components,
make sure to provide the "name" option.

Because I use transition compoent in my vue app

Then I try to remove transition component in vue app, the warning is disappeared

Simple test not working

Hello,

I've tried this code and it does not works.

Please can you check and tell me.
Thanks a lot

npx create-react-app my-app
cd my-app
npm i -S vuera
npm start

Attribute hyphenation

Hi, great library but I found a small issue:

When passing props to the React component, Vue hyphenation rules doesn't work as expected. E.g. <my-react-component :form-data="someData" /> has to be written as <my-react-component :formData="someData" />, which breaks standard Vue linting rules.

Workaround is to add <!-- eslint-disable vue/attribute-hyphenation --> to the templates where needed, but would be nice if this was handled automatically by vuera.

Babel return partial white page when compiled

Bug Report

Describe the bug

We are using vuera/babel in babel-loader plugin and it's returning a partial blank page after webpack compiles, but if we remove babel and use VueWrapper component it normally shows the component.

Command trace and repository with babel.

$ yarn install
$ yarn bs
$ yarn packages
$ cd examples/vue
$ yarn dev --debug

Code reference
https://github.com/pedronauck/docz/tree/feat/vue

Environment

  • Node/npm version: Node v9.11.2/npm 6.0.0

Thanks again @akxcv

Cannot use a component in multiple places

I tried using the resizable react component in vue. It works great if I use the component only once in a page, if i have more than one instances of the same component in a single page, the component that is created first is being used instead of a new component instance being created.

Project built with Vue TS component fails

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.

How to communicate between components

I'm using React in Vue.

Besides sending data to React with props and receiving events from React to Vue (eg:@myEvent="someHandler"), I'd like to be able to send events or call methods from the parent Vue component to the child React component.

In Vue this would be done with this.$refs.component.method(). I understand this is not an ideal approach from an architectural standpoint, but for certain use cases this is a valid approach.

So, how would this be accomplished with Vuera?

Eslint failing

I checked out the code to try to work on #50 and in my first checkin found eslint failing.

When I stash my changes and go back to master, it is still failing, so I think it probably has to do with a version change in eslint rather than the code I'm introducing.

The issue I see is:

kball-2:vuera kball$ npm run lint

> [email protected] lint /Users/kball/git/vuera
> eslint .

ImportDeclaration should appear when the mode is ES6 and in the module context.
AssertionError [ERR_ASSERTION]: ImportDeclaration should appear when the mode is ES6 and in the module context.
    at Referencer.ImportDeclaration (/Users/kball/git/vuera/node_modules/escope/lib/referencer.js:591:34)
    at Referencer.Visitor.visit (/Users/kball/git/vuera/node_modules/esrecurse/esrecurse.js:104:34)
    at Referencer.Visitor.visitChildren (/Users/kball/git/vuera/node_modules/esrecurse/esrecurse.js:83:38)
    at Referencer.Program (/Users/kball/git/vuera/node_modules/escope/lib/referencer.js:419:18)
    at Referencer.Visitor.visit (/Users/kball/git/vuera/node_modules/esrecurse/esrecurse.js:104:34)
    at Object.analyze (/Users/kball/git/vuera/node_modules/escope/lib/index.js:153:16)
    at EventEmitter.module.exports.api.verify (/Users/kball/git/vuera/node_modules/eslint/lib/eslint.js:892:35)
    at localVerify (/Users/kball/git/vuera/node_modules/eslint-plugin-html/src/index.js:107:14)
    at EventEmitter.eslint.verify (/Users/kball/git/vuera/node_modules/eslint-plugin-html/src/index.js:147:18)
    at processText (/Users/kball/git/vuera/node_modules/eslint/lib/cli-engine.js:264:31)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] lint: `eslint .`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] lint script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/kball/.npm/_logs/2018-07-30T22_08_57_613Z-debug.log

According to this eslint issue: eslint/eslint#10349 updating eslint is likely to resolve it.

Vue doesn't work in React

Hey there! I have a trouble with Vue component inside React. I'm using HOC API, like in docs (here).

But get an error:
InvalidCharacterError: Failed to execute 'createElement' on 'Document': The tag name provided ('/static/media/OpenApi.6037cdb6.vue') is not a valid name.

How I do that:

import React, {Component} from 'react'
import {BreadcrumbsItem} from 'react-breadcrumbs-dynamic'
import {VueInReact} from 'vuera'
import OpenApi from 'vue-openapi'
import {getApiData} from './actions'
import VueComponent from '../../../components/Vue/VueComponent.vue'

export default class Openapi extends Component {
	state = {
		json_api: {}
	}

	render () {
		const Component = VueInReact(OpenApi)
		return (
			<div>
				<BreadcrumbsItem to="/openapi">Open API</BreadcrumbsItem>
				<Component/>
				<vue-component></vue-component>
				<open-api></open-api>
			</div>
		)
	}

	async componentDidMount () {
		let data = await getApiData()

		console.log(data)

		this.setState({
			...this.state,
			json_api: data.data
		})
	}
}

In this case, and components didn't compiled. But (this is the way like in docs) shows me error above. Help! Thanks!

If I use wrapper component, console shows me:
Invalid Component definition

Events

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

Handle component update

Currently, in both React and Vue wrappers, if the component prop is changed, nothing happens.

Example:

import RegisteredUser from './RegisteredUser.vue'
import GuestUser from './GuestUser.vue'

const User = props => {
  const { registered, user } = this.props
  const Component = registered ? RegisteredUser : GuestUser
  return <Component user={user} />
}

Or, in Vue:

<template>
  <div>
    <registered-user v-if="registered" :user="user" />
    <guest-user v-else :user="user" />
  </div>
</template>
<script>
  import RegisteredUser from './RegisteredUser'
  import GuestUser from './GuestUser'

  export default {
    props: ['registered', 'user'],
    components: { RegisteredUser, GuestUser },
  }
</script>

We expect the component to change from RegisteredUser to GuestUser and back when we change the registered prop, but this does not happen, because both React and Vue wrappers essentially cache the component upon creation.

This use case is probably not very common, however, this should be handled correctly.

cannot use slate in vue project

Code as folowing:

<template>
  <div>
    <Editor :value="value" @change="onChange" />
  </div>
</template>

<script>
import { Editor } from 'slate-react'
import { Value } from 'slate'

const j = {
  document: {
    nodes: [
      {
        object: 'block',
        type: 'paragraph',
        nodes: [
          {
            object: 'text',
            leaves: [
              {
                text: 'A line of text in a paragraph.'
              }
            ]
          }
        ]
      }
    ]
  }
}

export default {
  name: 'slate',
  components: {
    Editor,
    Value
  },
  data() {
    return {
      value: Value.fromJSON(j)
    }
  },
  methods: {
    onChange(v) {
      console.log('on change:', v)
      this.value = v
    }
  }
}

</script>

<style>

</style>

the editor can display, but cannot edit.

React Native with Vue?

Hi,
Is it possible to use React native with Vue? There were no information about this in readme

React component in Vue

I want to use ReactTable this component in Vue, I use VuePlugin, but did not succeed

 <react-table :data="data" :columns="columns"/>

import ReactTable from "react-table";
import "react-table/react-table.css";

      data: [
        {
          name: "Tanner Linsley",
          age: 26,
          friend: {
            name: "Jason Maurer",
            age: 23
          }
        }
      ],
      columns: [
        {
          Header: "Name",
          accessor: "name"
        },
        {
          Header: "Age",
          accessor: "age"
        },
        {
          id: "friendName",
          Header: "Friend Name",
          accessor: "friend.name"
        },
        {
          Header: "friendAge",
          accessor: "friend.age"
        }
      ]

problem with flow?

https://github.com/stlbucket/vue-graphiql

in the above repo, i have created a new vue cli 3 app, then tried to incorporate the graphiql react component via vuera

i've been able to get past a number of webpack hurdles, but there seems to be a problem with some flow files when running yarn serve

 warning  in ./node_modules/graphql-language-service-interface/dist/getDiagnostics.js.flow

Module parse failed: Unexpected token (11:12)
You may need an appropriate loader to handle this file type.
|  */
|
> import type {
|   ASTNode,
|   DocumentNode,

 @ ./node_modules/graphql-language-service-interface/dist sync ^.*$
 @ ./node_modules/graphql-language-service-interface/dist/GraphQLLanguageService.js
 @ ./node_modules/graphql-language-service-interface/dist/index.js
 @ ./node_modules/codemirror-graphql/hint.js
 @ ./node_modules/graphiql/dist/components/QueryEditor.js
 @ ./node_modules/graphiql/dist/components/GraphiQL.js
 @ ./node_modules/graphiql/dist/index.js
 @ ./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/babel-loader/lib??ref--14!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/App.vue?vue&type=script&lang=js&
 @ ./src/App.vue?vue&type=script&lang=js&
 @ ./src/App.vue
 @ ./src/main.js
 @ multi (webpack)-dev-server/client?http://192.168.1.100:8080/sockjs-node (webpack)/hot/dev-server.js ./src/main.js

this happens for seven files, i believe, and always at the import directive.

vuejs/vue-cli#1810
and
https://www.npmjs.com/package/flow-babel-webpack-plugin

are the last two things i've come to, but the plugin seems to have no effect.

vue.config.js:

const FlowBabelWebpackPlugin = require('flow-babel-webpack-plugin');
const path = require('path')

module.exports = {
  pluginOptions: {
    apollo: {
      enableMocks: true,
      enableEngine: false
    }
  },
  devServer: {
    proxy: {
      "/graphql": {
        target: "http://localhost:5000"
      }
    }
  },
  configureWebpack: {
    plugins: [
      new FlowBabelWebpackPlugin()
    ],
    resolve: {
      alias: {
        graphql$: path.resolve(__dirname, 'node_modules/graphql/index.js')
      },
      extensions: [ '.flow', '.mjs', '.js', '.json', '.jsx', '.css' ]
    },
    module: {
      rules: [
        {
          test: /\.jsx?$/,
          loader: 'babel-loader',
          exclude: /node_modules/,
          query: {
            cacheDirectory: true,
            presets: ['@babel/preset-env', '@babel/preset-react']
          }
        }
      ]
    }
  }
}

package.json:

{
  "name": "vue-graphiql",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint"
  },
  "dependencies": {
    "bfj": "^6.1.1",
    "graphiql": "^0.12.0",
    "graphql": "^13.0.2",
    "prop-types": "^15.6.2",
    "react": "^16.5.2",
    "react-dom": "^16.5.2",
    "vue": "^2.5.17",
    "vuera": "^0.2.2"
  },
  "devDependencies": {
    "@babel/core": "^7.0.0-0",
    "@babel/preset-env": "^7.1.0",
    "@babel/preset-flow": "^7.0.0",
    "@babel/preset-react": "^7.0.0",
    "@vue/cli-plugin-babel": "^3.0.3",
    "@vue/cli-plugin-eslint": "^3.0.3",
    "@vue/cli-service": "^3.0.3",
    "babel-loader": "^8.0.2",
    "flow-babel-webpack-plugin": "^1.1.1",
    "vue-template-compiler": "^2.5.17"
  },
  "eslintConfig": {
    "root": true,
    "env": {
      "node": true
    },
    "extends": [
      "plugin:vue/essential",
      "eslint:recommended"
    ],
    "rules": {},
    "parserOptions": {
      "parser": "babel-eslint"
    }
  },
  "postcss": {
    "plugins": {
      "autoprefixer": {}
    }
  },
  "browserslist": [
    "> 1%",
    "last 2 versions",
    "not ie <= 8"
  ]
}

_class is undefined

Hey, I tried using some office fabric ui react components with this library and ran into a problem with the Persona component. Other react components I tried so far worked however.

Stack trace:

TypeError: Cannot read property 'displayName' of undefined
    at makeReactContainer (vuera.cjs.js?866f:336)
    at VueComponent.mountReactComponent (vuera.cjs.js?866f:349)
    at VueComponent.mounted (vuera.cjs.js?866f:359)
    at callHook (vue.esm.js?efeb:2921)
    at Object.insert (vue.esm.js?efeb:4158)
    at invokeInsertHook (vue.esm.js?efeb:5960)
    at Vue.patch [as __patch__] (vue.esm.js?efeb:6179)
    at Vue._update (vue.esm.js?efeb:2660)
    at Vue.updateComponent (vue.esm.js?efeb:2788)
    at Watcher.get (vue.esm.js?efeb:3142)

This is the line throwing the error, with _class being undefined at vuera.cjs.js#336:

_class.displayName = 'ReactInVue' + (Component.displayName || Component.name || 'Component'), _temp;

Warning: Invalid value for prop `click` on <button> tag. Either remove it from the element, or pass a string or number value to keep it in the DOM. For details, see https://fb.me/react-attribute-behavior

I'm trying to use Evergreen UI, which is a UI toolkit for React, in a testing vue app.
I've noticed that buttons don't handle click events correctly, in fact when I press a button a dialog should appear because of the change of a variable in the main component data dict, but it's doesn't.
Upon futher inspection I've noticed that the variable doesn't get updated at all and I get this error on the browser console:

webpack-internal:///../node_modules/fbjs/lib/warning.js:33 Warning: Invalid value for prop `click` on <button> tag. Either remove it from the element, or pass a string or number value to keep it in the DOM. For details, see https://fb.me/react-attribute-behavior
    in button (created by Box)
    in Box (created by Text)
    in Text (created by Button)
    in Button (created by ReactInVueButton)
    in ReactInVueButton

Notice that I don't get any error on the terminal after running vue serve.
Here's my code

<template>
  <div id="app">
    <Button appearance="green" @click="showDialog">This is EvergreenUI ๐ŸŒฒ for React, in VueJS! ๐Ÿ˜Š</Button>
    <CornerDialog :isShown="shown">Hello I'm a corner dialog!</CornerDialog>
  </div>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'
import {Button, CornerDialog} from 'evergreen-ui'

export default {
  name: 'app',
  data() {
    return {shown: false}
  },
  components: {
    HelloWorld,
    Button,
    CornerDialog
  },
  methods: {
    showDialog() {
      this.shown = true;
    }
  }
}
</script>

Distribution file compatibility

This issue came up because of IE11, but I totally understand if including support for IE11 is not something within the scope of this library. It looks like es2015 compatibility is desired based on the .babelrc:

"es2015": {

However, both Object.assign and Object.entries appear in the built common js file:

Object.assign(this.vueInstance.$data, props);

var wrappedComponents = mergedValue ? Object.entries(mergedValue).reduce(function (acc, _ref) {

I always forget which level Object.assigns is at, but I believe Object.entries is much more recent? Is this maybe a bug in the rollup or babel configuration during the build?

Thanks!

Doesn't work with styled-components

Hi there, thanks for this great library!

styled-components fails the isReactComponent test, which means it doesn't get rendered at all.

This is how a styled-component looks like:
screenshot 2018-11-30 15 30 04

I'll open a PR to address this soon. Cheers!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.