• Stars
    star
    296
  • Rank 139,731 (Top 3 %)
  • Language
    JavaScript
  • Created over 5 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Use Svelte components with Vue and React

svelte-adapter

A simple utility that allows you to use Svelte components inside React or Vue components.

There is an adapter each for Vue and React which allows you to pass props and respond to events in a way that makes sense for that library.

This isn't a perfect solution, there are some limitations.


Install

With npm:

npm install svelte-adapter

Or with yarn:

yarn add svelte-adapter

Use it

Each 'adapter' is a simple function that takes a svelte component and a few options and returns a Vue or React component that can be used in Vue templates or JSX as you would expect. The returned components will always have a wrapper element, by default this is a <span> but it can be customised.

The adapters both have the same signature:

adapter(Component: SvelteComponent, styleObject?: object, wrapperElement?: string) : Component
  • Component should be a compiled svelte component, either precompiled or compiled as part of your build step using rollup-plugin-svelte for rollup or svelte-loader from webpack.
  • styleObject (optional) should be an object of styles that will be applied to the base elemement. This should be a valid JavaScript object with camelCased css property names. This defaults to an empty object.
  • wrapperElement (optional). All component have a base 'wrapper' element, by default this is a <span> but you can pass in a string to customise this behaviour (eg: 'div', 'li', etc.) If need a specific wrapper element but don't care about styles, you can simply pass an empty object as the styleObject.

In the examples below, the Svelte component we will be using is a simple component that accepts a prop that will be rendered and emits an event upon clicking a button.

<script>
  import { createEventDispatcher } from 'svelte';

  export let number = 0;
  const dispatch = createEventDispatcher();
</script>

<h1>{ number }</h1>
<button on:click={ () => dispatch('magicalclick') }>
  Click Me
</button>

Examples

React

Try it on codesandbox

The React-Svelte adapter is the default export from svelte-adpater/react.

The implementation of the React adapter uses hooks so you will need a recent version of React for this to work. If necessary I could add a class-based version at some stage.

Using the adaptor is very straight-forward, the adapter is a Higher Order Component that takes a Svelte component and returns a React component. The below example assumes your are compiling Svelte components as they are imported using webpack or rollup. If not, just import the compiled javascript file instead.

Svelte components can emit events which doesn't quite make sense in React. Any events emitted by the svelte component can be passed callbacks via an on* prop containing a function, this function will fire when the event is emitted. Any prop that starts with on followed by a capital letter is assumed to be an event and will be used to add a listener. onClick will fire the provided callback when 'click' events are emitted, onSomethingRandom will do the same for 'somethingRandom' events. This does not interfere with props that have the same naming convention, they will all be passed regardless.

Some Svelte component's allow you to bind to internal data which doesn't make too much sense outside of Svelte yet they often form an important part of the API. Instead I have added the option to use a watch* prop (similar to the on* prop). This also takes a callback function and recieves the value you wish to watch as its only argument. watchNumber={ n => setCount(n) } would watch the internal value number, when number changes the callback you passed to it would be executed receiving the new number value as its only argument.

This may seem strange but many Svelte components are written to make use of this bind syntax, without it there is often a hole in the API leaving you unable to respond to internal state changes. You will probably want to control your state with React, this watch* prop is an escape hatch that allows you to pull out those internal values to use however you wish.

Normal props behave as you would expect.

import React, { useState } from "react";
import toReact from "svelte-adapter/react";

import SvelteApp from "../App.svelte";

const baseStyle = {
  width: "50%"
};

const SvelteInReact = toReact(SvelteApp, baseStyle, "div");

const App = () => {
  const [count, setCount] = useState(10);

  const handleClick = () => setCount(prevCount => prevCount + 1);

  return (
    <div>
      <SvelteInReact
        number={count}
        onMagicalclick={handleClick}
        watchNumber={n => setCount(n)}
      />
      <button onClick={handleClick}>Increment - {count}</button>
    </div>
  );
};

Vue

Try it on codesandbox

The Vue-Svelte adapter is the default export from svelte-adpater/vue.

Using the adapter is very straight-forward, the adapter is a Higher Order Component that takes a Svelte component and returns a Vue component. The below example assumes your are compiling Svelte components as they are imported using webpack or rollup. If not, just import the compiled javascript file instead.

Since Vue has an event mechanism similar to Svelte, event directives can be used as expected. v-on:* or @* directives will listen for the matching events on the Svelte component. v-on:click or @click will fire the provided callback when 'click' events are emitted, v-on:somethingRandom or @somethingrandom will do the same for 'somethingRandom' events. Other props behave as you would expect.

Some Svelte component's allow you to bind to internal data which doesn't make too much sense outside of Svelte yet they often form an important part of the API. I have added the option to use a @watch:* prop (similar to the @:* prop). This also takes a callback function and recieves the value you wish to watch as its only argument. @watch:number="setCount" would watch the internal value number, when number changes the callback you passed to it would be executed receiving the new number value as its only argument.

This may seem strange but many Svelte components are written to make use of this bind syntax, without it there is often a hole in the API leaving you unable to respond to internal state changes. You will probably want to control your state in a Vue component, this @watch:* prop is an escape hatch that allows you to pull out those internal values to use however you wish.

Normal props behave as expected.

<template>
  <div>
    <SvelteInVue
      :number="count"
      @magicalclick="handleClick"
      @watch:number="setCount"
    />
    <button @click="handleClick">Increment - {{ count }}</button>
  </div>
</template>

<script>
import SvelteApp from "../App.svelte";
import toVue from "svelte-adapter/vue";

const baseStyle = {
  width: "50%"
};

export default {
  components: {
    SvelteInVue: toVue(SvelteApp, baseStyle, "div")
  },
  data() {
    return {
      count: 0
    };
  },
  methods: {
    handleClick() {
      this.count += 1;
    },
    setCount(n) {
      this.count = n;
    }
  }
};
</script>

Limitations

While everything should work in most situations, it is not currently possible to pass children or slots to Svelte components with these adapters.

This won't work with any of the adpaters:

<SvelteComponent>
  <p>Hello</p>
</SvelteComponent>

There may be more limitations that I am unaware of, this package is really just intended a simple way to use Svelte and should work most of the time. The code is short and simple, if you have specific needs you will probably be better off writing something custom for your application.

More Repositories

1

MDsveX

A markdown preprocessor for Svelte.
JavaScript
2,346
star
2

svelte-travel-transitions

Native-like Page Transitions with SvelteKit, A Travel App.
Svelte
195
star
3

REPLicant

REPLicant - Svelte Summit 2020. The Accompanying source code and additional information.
CSS
82
star
4

prism-svelte

Svelte language extension for prismjs
JavaScript
65
star
5

svelte-adaptive-sensors

Sensors to deliver adaptive loading based on a user's device and network
JavaScript
50
star
6

peng-move

Svelte
47
star
7

gradio-imageslider

ImageSlider custom component for gradio.
Svelte
26
star
8

svelte-test

Testing utilities for Svelte
JavaScript
25
star
9

bristech-2019

Slides for "Rerendering Perceptions with Svelte" talk - Bristech 2019
JavaScript
19
star
10

mdsvex-playground

:o
JavaScript
18
star
11

sapper-rollup-postcss

Sapper rollup template with postcss, autoprefixer and tailwind.
JavaScript
12
star
12

sapper-mdsvex-template

JavaScript
12
star
13

sapper-graphql

Sapper and GraphQL
JavaScript
8
star
14

pengifs

JavaScript
8
star
15

sv-emotion

Emotion and Svelte
JavaScript
6
star
16

svelte-worker

POC preprocessor for svelte that auto-workerises reactive declarations.
JavaScript
6
star
17

mdsvex-template

A simple template for mdsvex with SvelteKit
Svelte
6
star
18

sapper-v3

Sapper template for Svelte 3
JavaScript
5
star
19

sapper-pe-test

An attempt at making sapper perform static server-side form validation
JavaScript
4
star
20

remark-class-names

Remark plugins to add custom class names to markdown elements
JavaScript
3
star
21

uphill-start

Svelte
3
star
22

svelte-window-variables

Svelte preprocessor to add component variables to the window during tests.
JavaScript
3
star
23

mdsvex-math

JavaScript
2
star
24

svelte-react-template

A very basic svelte-react rollup template
JavaScript
2
star
25

sapper-webpack-postcss

Sapper webpack template with postcss, autoprefixer and tailwind.
JavaScript
2
star
26

2880-gradio-next

test - gradio#2880
CSS
2
star
27

nimbus

a weather app
HTML
2
star
28

utils

Simple utility functions for when you need a simple utility function.
JavaScript
2
star
29

obsidian-plugins-books

TypeScript
2
star
30

sv3-todomvc

Svelte 3 - ToDoMVC
CSS
2
star
31

svelte-pages-kit

Svelte
1
star
32

snowpack-fork

JavaScript
1
star
33

sapper-pixi-example

JavaScript
1
star
34

sapper-scss

Sample sapper app with scss support via svelte-preprocess
JavaScript
1
star
35

ryfill-sapper-mdsvex

JavaScript
1
star
36

tauri-budapest

Svelte
1
star
37

actions-test

testing actions
1
star
38

local-infer-m1-zephyr

Python
1
star
39

space-test-one

asd
HTML
1
star
40

sw-blob-test

HTML
1
star
41

kit-mdsvex-dynamic-data

Svelte
1
star
42

uphill-workshop-notes

Svelte
1
star