Skip to content

Render React components inside your ember templates

License

Notifications You must be signed in to change notification settings

poulet42/ember-x-react

Folders and files

NameName
Last commit message
Last commit date

Latest commit

aa2cc6e · Jan 27, 2025

History

32 Commits
Jan 26, 2025
Jan 25, 2025
Jan 27, 2025
Jan 27, 2025
Jan 25, 2025
Jan 25, 2025
Jan 25, 2025
Jan 25, 2025
Jan 27, 2025
Jan 27, 2025
Jan 25, 2025
Jan 25, 2025
Jan 27, 2025
Jan 26, 2025
Jan 26, 2025
Jan 27, 2025
Jan 25, 2025

Repository files navigation

ember-x-react

Render React components inside your ember templates:

<XReact::Root>
  <XReact @component={{this.Form}} @props={{hash onSubmit=this.handleSubmit}}>
    <label for='first-name'>{{t 'my-form.first-name'}}</label>
    <XReact
      @component={{this.TextField}}
      @props={{hash id='first-name' name='first-name'}}
    />
    <XReact @component={{this.Button}} @props={{hash type='submit'}}>
      {{t 'my-form.submit'}}
    </XReact>
  </XReact>
</XReact::Root>

Features

✅ Supports nested React components and composition

✅ Supports React Context

✅ Low runtime footprint: XReact components are transformed into react components at build time !

✅ Use ember and react features together: Conditional components in a {{#if}} block, pass @tracked properties in props

✅ Supports DOM elements as children

✅ Props type safety in the template

Limitations

❌ You cannot use the yield keyword inside a XReact component

❌ You cannot have ember components inside XReact components

Compatibility

  • Ember.js v4.12 or above
  • Embroider or ember-auto-import v2

Installation

ember install ember-x-react

Setup

Add the babel plugin in your config:

Most of the transformation logic is made at build time via a babel plugin; Add the plugin in your ember-cli-build.js configuration:

new EmberApp(defaults, {
  babel: {
    plugins: [
      // ...
      require('ember-x-react').buildBabelPlugin(),
    ],
  },
});

or directly in your Babel config file if you enabled useBabelConfig: true

Update your bundler configuration to handle JSX:

if your app is using embroider with webpack, you need to tell webpack how to handle JSX:

rules: [
  // ...
  {
    test: /\.jsx/, // replace or add tsx if you use typescript
    use: {
      loader: 'babel-loader',
      options: {
        presets: [
          // Add other presets here if you need Typescript support for example
          ['@babel/preset-react', { runtime: 'automatic' }],
        ],
      },
    },
  },
];

Usage

Simple usage

import XReactRoot from 'ember-x-react/components/x-react/root';
import XReact from 'ember-x-react/components/x-react';
import MyButton from './my-button.tsx';

export default class MyForm extends Component {

  ...

  get isFormPending() {
    return this.submitTask.isPending;
  }

  <template>
    <form>
      <MyEmberDropdown />
      <XReact::Root>
        <XReact @component={{MyButton}} @props={{hash isPending=this.isFormPending}}>
          {{#if this.isFormPending}}
            Submitting ...
          {{else}}
            Submit
          {{/if}}
        </XReact>
      </XReact::Root>
    </form>
  </template>
}

What about context providers ?

The components passed to XReact can be any valid React components, this means you can just do:

<template>
  <XReact::Root>
    <XReact @component={{MyIntlProvider}}>
      <XReact @component={{FormattedMessage}} @props={{id="hello.world"}} />
    </XReact>
  </XReact::Root>
</template>

Usage with HBS templates

Create a backing component class for your HBS template, then add the React component as a property of this class:

import { MyButton } from './my-button.tsx';

export default MyEmberComponent extends Component {
  myReactButton = MyButton;
}

Then, you can render your react component by referencing the class property:

<XReact @component={{this.myReactButton}} />

Contributing

See the Contributing guide for details.

License

This project is licensed under the MIT License.