I am really new to Svelte, but cannot find answer to my question anywhere.
I am trying to use this React component in Svelte: https://developer.microsoft.com/en-us/fabric#/controls/web/stack (I guess it could be any React component and it would be the same problem)
However whenever i add it the entire app turns Blank.
Is it at all possible to import react components, if yes, how?
I have tried just to import it - which just destroys the app.
<script>
import { Stack, IStackProps } from 'office-ui-fabric-react/lib/Stack';
let name = 'world';
</script>
<h1>Hello {name}!</h1>
<input type="text" bind:value={name}/>
<Stack horizontal tokens={{ childrenGap: 50 }} >
<div>test</div>
</Stack>
-
no, they are not compatibleThomas– Thomas2019年05月26日 12:12:51 +00:00Commented May 26, 2019 at 12:12
-
So there are no way to use React components in Svelte?user1745605– user17456052019年05月26日 12:26:31 +00:00Commented May 26, 2019 at 12:26
-
1well, you can render a react app inside a svelte app, and vice versaThomas– Thomas2019年05月26日 12:34:28 +00:00Commented May 26, 2019 at 12:34
-
1Thanks Thomas, do you know where I can find some info on how to render a react app in Svelte?user1745605– user17456052019年05月26日 17:17:47 +00:00Commented May 26, 2019 at 17:17
-
Is it a substantial code base? You're probably better off rewriting them. The two paradigms are very different.jcollum– jcollum2019年05月27日 18:31:23 +00:00Commented May 27, 2019 at 18:31
4 Answers 4
Artur Mustafin has answered this question in his article React.Component wrapper for Svelte.
<script>
import { onMount } from "svelte";
import React from "react";
import ReactDOM from "react-dom";
const e = React.createElement;
class LikeButton extends React.Component {
constructor(props) {
super(props);
this.state = { liked: false };
}
render() {
if (this.state.liked) {
return "You liked this.";
}
return e("button", { onClick: () => this.setState({ liked: true }) }, "Like");
}
}
let container;
onMount(function() {
ReactDOM.render(e(LikeButton), container);
});
</script>
<div bind:this={container}/>
1 Comment
Uncaught ReferenceError: process is not defined (checkPropTypes.js:12)With svelte-preprocess-react you're able to use react components by prefixing the tag with react: so <Stack> would become <react:Stack>:
<script>
import { Stack } from 'office-ui-fabric-react';
</script>
<react:Stack horizontal tokens={{ childrenGap: 50 }} >
<div>test</div>
</react:Stack>
Comments
Check this repo: https://github.com/jpinho/svelte-react-material
I developed a utility class called ReactAdapter that can inject any React components into Svelte. The code is based on RichHarris/react-svelte.
Also, the project serves as a template to demo how you can have Svelte and React living side by side.
Example usage of the ReactAdapter would be:
<script>
import Button from "@material-ui/core/Button";
import ReactAdapter from "./utils/ReactAdapter.svelte";
</script>
<ReactAdapter
el={Button}
class="mui-btn"
children="Hello"
variant="contained"
color="primary"
onClick={() => alert("hello world!")}
/>
<style>
/**
* Styling a React Component from within a Svelte Component.
*/
:global(.mui-btn) {
margin: 20px;
}
</style>
4 Comments
Svelte is a not only a framework but also a compiler that compiles the Framework code into vanilla JavaScript. It also supports JSX syntax, which is a syntax that React uses to create components. so we can just put a react component directly in ./src
import React from "react";
import Youtube from "react-youtube";
export const YouTubeWrapper: React.FC<React.PropsWithChildren> = () => {
return (
<>
<h2>Youtube video demo</h2>
<YouTube videoId="uH6aRpwTEF0" />
</>
);
};
This means that we are be able to use React components directly in Svelte with some tweaks. something like below:
<script lang="ts">
import { onMount, onDestroy } from 'svelte';
import React from 'react';
import ReactDOM from 'react-dom/client'; // Updated import for createRoot
import {YouTubeWrapper} from "../YoutubeWrapper";
let root: ReactDOM.Root;
let youtubeReactComponent: ReactDOM.Container;
const renderNotifiCardModal = (youtubeReactComponent: ReactDOM.Container) => {
root = ReactDOM.createRoot(youtubeReactComponent)
root.render(React.createElement(YouTubeWrapper, {}, null))
}
onMount(() => {
renderNotifiCardModal(youtubeReactComponent )
});
onDestroy(() => {
if (root) {
root.unmount(); // Use the unmount method on the root
}
});
</script>
<div bind:this={youtubeReactComponent}></div>
Here is the full example code
However, the native React code in Svelte does not look straight forward. Alternatively, we can utilize svelte-preprocessor-react which is much easier like below:
<script lang="ts">
import { onMount, onDestroy } from 'svelte';
import React from 'react';
import ReactDOM from 'react-dom/client'; // Updated import for createRoot
import {YouTubeWrapper} from "../YoutubeWrapper";
</script>
<react:YouTubeWrapper />
Much simpler 🚀. You can also check out the full example code herewith
NOTE for
svelte-preprocessor-reactwe need to make a tweak in react component. See the example here