Can we integrate react component into Aurelia project?
Asked Answered
C

1

5

I have created one react component and build it using webpack and deployed on server. I want to integrate this component into Aurelia Project.

I tried using below npm module: https://www.npmjs.com/package/aurelia-react-loader

In above module mentioned, component name need pass into html file. like in example my-react-component.js is passing into html file.

But my React Component is loading into root in html tag using below code:

    import React from 'react';
    import ReactDOM from 'react-dom';
    import App from './App';
    ReactDOM.render((
      <App/>
    ), document.getElementById('root'));

and after running webpack module, it is creating one JavaScript file that is called index_bundle.js file. Here imported App module is main js component. It is rendering into index.html on root element via ReactDOM.

So I am not sure, How I am going to integrate React component link or url into Aurelia application?

Please let me know if you have any doubts in question. I can do explain in detail.

Thanks in advance. Harish

Ced answered 18/9, 2017 at 14:57 Comment(1)
A bit late to the party, but I've built an aurelia-skeleton with typescript and react a while ago. Maybe it's still of use to you.Beaston
A
10

Yeah, it's really easy to integrate a react component in to an Aurelia app. Check out my project where I do just that here: https://github.com/ashleygrant/aurelia-loves-react

I'm not even using the loader plugin you mentioned.

Here's how to wrap a third-party react component in an Aurelia custom element:

import React from 'react';
import ReactDOM from 'react-dom';
import ReactDatePicker from 'react-datepicker';
import { noView, bindable, inject } from 'aurelia-framework';

@noView(['react-datepicker/react-datepicker.css'])
@inject(Element)
export class DatePicker {
  @bindable selectedDate;
  @bindable onChange;

  constructor(element) {
    this.element = element;
  }

  selectedDateChanged() {
    this.render();
  }

  render() {
    ReactDOM.render(
      <ReactDatePicker
        selected={this.selectedDate}
        onChange={date => this.onChange({ date: date })}
      />,
      this.element
    );
  }

  // How to use native DOM events to pass the changed date
  /*render() {
    ReactDOM.render(
      <ReactDatePicker
        selected={this.selectedDate}
        onChange={date => {
          let event = new CustomEvent('change', { 'detail': date });
          // Dispatch the event.
          this.element.dispatchEvent(event);
        }
        }
      />,
      this.element
    );
  }*/
}

And here's how to do it while using a custom react component that is part of the Aurelia project:

import React from 'react';
import ReactDOM from 'react-dom';
import { noView, bindable, inject } from 'aurelia-framework';
import FormattedDate from '../react-components/formatted-date';

@noView()
@inject(Element)
export class ReactDate {
  @bindable date;
  @bindable format = 'dddd, MMMM D, YYYY';

  constructor(element) {
    this.element = element;
  }

  dateChanged() {
    this.render();
  }

  formatChanged() {
    this.render();
  }

  render() {
    ReactDOM.render(
      <FormattedDate 
        date={this.date}
        format={this.format}
      />,
      this.element
    );
  }
}

As you can see, it's pretty simple. I like doing it by hand rather than using the loader as I can set up databinding for each property so it works in a more "Aurelia-ey" way.

Applecart answered 18/9, 2017 at 16:17 Comment(13)
Thanks a lot. I am looking into your project and will try to implement in my project. I will get back to you if will have any questions.Ced
Hi, In your project I have seen react-date.js file. In that you imported aurelia-framework. It is required to add in React component? My compoment main file is:Ced
import React from 'react'; import ReactDOM from 'react-dom'; import App from './App'; export class ReactComponent { constructor() { this.render(); } render() { console.log("called RENDER function") ReactDOM.render(( <App/> ), document.getElementById('root')); } } And I am integrating into Aurelia like this: <template> <require from="../react/index_bundle"></require> <react-component></react-component> </template>Ced
But I am seeing render function is not calling. Even the log in render function is not coming in log section. Please let me know what I am doing wrong here?Ced
You can't render something that hasn't got a place to be put in the DOM yet. So don't call render in the constructor, call it in the attached callback.Applecart
Also, why are you using document.getElementById in your code? Use Aurelia to get the element passed to you like I do in the example code.Applecart
document.getElementById I am using into React component for loading into root element. You imported aurelia-framework into React component. As I understood. Correct? I need to import same way aurelia-framework into React component? FYI, In above code, imported App component is main React component of my application. Can you tell me what should be code here from React Component side? Current component main file code is below.Ced
import React from 'react'; import ReactDOM from 'react-dom'; import App from './App'; export class ReactComponent { constructor() { this.render(); } render() { console.log("called RENDER function") ReactDOM.render(( <App/> ), document.getElementById('root')); } }Ced
I don't think you've looked at the repository of code I posted. I posted an Aurelia app that loads up a couple of React components as custom elements in the Aurelia app. If you just want to render a react component in to a single element with an id of root in your page, there's no need to use Aurelia at all. That's just creating a react application.Applecart
But if you want to integrate that react component (called App in your code) in to an Aurelia application as a custom element then you CAN NOT use document.getElementByid. What if you want to use the React component in more than one place? That is why I have Aurelia inject the element in to my custom element's view model and pass that element to ReactDOM.render.Applecart
And finally, I already said that calling ``ReactDOM.render` in the constructor of your Aurelia component is not going to work. The stuff in your custom element's template, such as the <div id="root"></div> that I'm assuming is in your custom element's template simply don't exist in the DOM until the attached callback happens.Applecart
What is index_bundle that is being required in? I have no idea what you are doing in your code. Please go look carefully at the repository I posted and see how I am doing this. Again, that code is here: github.com/ashleygrant/aurelia-loves-react I've given you everything you need to do this, but you seemingly have tried to only pay attention to about 25% of the code I posted. You need to look at the entirety of the code, not just small parts.Applecart
I am really impressed by how easy this was to get working. I just followed the examples and everything worked (forgot to call render the first time). I have a custom setup where I am loading everything through plugin-typescript and plugin-babel under JSPM 0.17. I wrote my React component as .tsx and the adapter as .js. Worked beautifully. Thanks Ashely!Nuptial

© 2022 - 2024 — McMap. All rights reserved.