Use ReactJS components in ReScript React project

Dear ReScript experts,

I’m trying to find a way to import existing ReactJS components into the ReScript React project:

// Foo.js

import React from 'react'

export default function Foo() {
    return (
        <h1>Foo</h1>
    )
}
// FooWrapper.res

module Foo = {
  @react.component @module("./Foo")
  external make: unit => React.element = "Foo"
}

@react.component
let make = () => {
  <div> <Foo /> </div>
}

I’m getting a webpack error:

ERROR in ./src/Foo.js 5:8
[1] Module parse failed: Unexpected token (5:8)
[1] You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
[1] | export default function Foo() {
[1] |     return (
[1] >         <h1>Foo</h1>
[1] |     )
[1] | }
[1]  @ ./src/FooWrapper.bs.js 3:10-26
[1]  @ ./src/Main.bs.js
[1]  @ ./src/Index.bs.js

What would be the right way of doing it?

Many thanks!
Sergei

It seems like you are missing or have misconfigured the loader so webpack can’t recognize JSX syntax in Foo.js.

1 Like

I think that you should flip @react.component @module("./Foo")
to @module("./Foo") @react.component

But that does not change anything in the js file.

playground1

vs
playground2

1 Like

Thank you all so much for the help!
Renaming the file to .jsx and configuring the babel loader in webpack helped (also I tried vite - it worked straightaway).


Just leaving this for the record:

// Foo.jsx
import React from 'react'

function Foo() {
    return (
        <h1>Foo</h1>
    )
}

export { Foo }
// FooWrapper.res

module Foo = {
  @react.component @module("./Foo.jsx")
  external make: unit => React.element = "Foo"
}

@react.component
let make = () => {
  <div> <Foo /> </div>
}
// babel.config.json
{
    "presets": [
        "@babel/preset-env",
        "@babel/preset-react"
    ]
}
// webpack.config.js

module.exports = {
  ...
  module: {
    rules: [
      ...
      {
        test: /\.jsx$/,
        exclude: /(node_modules|bower_components)/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: [
              ['@babel/preset-env', { targets: "defaults" }]
            ]
          }
        }
      }
    ]
  }
};

4 Likes

Probably this because the component using default export.

Try to use the export named component in your React.js component.

export function Foo()

In case anyone else runs across this issue as I did, the default import for the “Foo” component above would look like this:

module Foo = {
  @react.component @module("./Foo")
  external make: unit => React.element = "default"
}

I found this documentation helpful on sorting out these interop issues: Import from / Export to JS | ReScript Language Manual.

2 Likes