Giter Club home page Giter Club logo

rescript-react's Introduction

@rescript/react

The Official ReScript Bindings for ReactJS

Versions

@rescript/react ReScript ReactJS Documentation
0.12.0+ 11.0+ 18.0.0+ Link
0.11.0 10.1 18.0.0+ Link
0.10.3 8.3 16.8.1+ Link

Development

npm install

# Starts the ReScript compiler in watch mode
npm start

Acknowledgements

This project is the next evolution of the original reason-react bindings.

rescript-react's People

Contributors

benfaerber avatar bloodyowl avatar chenglou avatar cknitt avatar cristianoc avatar cwstra avatar faheempatel avatar fhammerschmidt avatar glennsl avatar hyunseob avatar jderochervlk avatar lukasdeco avatar mununki avatar ozanmakes avatar rickyvetter avatar ryyppy avatar scotttrinh avatar sudo97 avatar tolluset avatar tom-sherman avatar whitchapman avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rescript-react's Issues

Have a way to create components with props = domProps

There are use-cases where you want to create components that replicate native dom elements, such as <button>, <a>, etc.

For that, you'd need something like ReactDOM.domProps, but as a @obj makeProps binding.

Maybe this issue is not relevant when we finally ship JSX v4, but would still be great to have a streamlined solution for current JSX v3 users.

Related discussions:

`onReset` is not allowed on form properties

rescript-react doesn't allow onReset prop on <form> element. (I think it should allow?)

Example:

let onSubmit = event => {
  Js.log("submitted")
}

let onReset = event => {
  Js.log("resetted")
}

@react.component
let make = () => {
  <form onSubmit onReset>
    <input type_="submit" value="Submit" />
    <input type_="reset" value="Reset" />
  </form>
}

Error:

[E] Line 11, column 17:
The function applied to this argument has type
    (
  ~?key: string,
  ~?ref: ReactDOM.domRef,
  /* skip */
) => ReactDOM.Props.domProps
This argument cannot be applied with label ~onReset

Wrap existing React component library in JS with invalid prop names

I have a React component <Switch type="switch | checkbox" /> from a JS library, can I import it to ReScript and make it take an argument of ~type_: [#switch_ | #checkbox]?

I have tried the @as annotation in arguments of the external make function, but it doesn't work well with @react.component. @string [@as("switch") #switch_ | #checkbox] works, but @as("type") ~type_: still compiles to type_ where <Switch /> is used.

RescriptReactErrorBoundary not working in v0.11

I described it in the forum
but here it goes as well

prior to the upgrade to v0.11 I was using this

<RescriptReactErrorBoundary
    fallback={_err => <div> {"An error occurred"->React.string} </div>}>
     <Viewer />    
</RescriptReactErrorBoundary>

The compiler is now throwing this error

This has type:
(
  ~children: React.element,
  ~fallback: RescriptReactErrorBoundary.params<'a> => React.element,
) => React.element
Somewhere wanted: React.component<'b> (defined as 'b => Jsx.element)

any idea why it is now not working?

Notes on apis

  • ReactDOMRe.objToDOMProps -> this function is currently missing, probably need to add that back for the transition (later on we will not need that apis for v1 afaik)

Upgrade notes:

  • ReasonReact.reactElement -> React.element
  • ReactDOMRe.Style -> ReactDOM.Style
  • ReactDOMRe.props -> ReactDOM.props
  • ReasonReact.string, ReasonReact.int,... -> React.string, React.int,...

Implementation ErrorBoundary component with jsx ppx

ErrorBoundary is implemented by using jsx ppx now, but it has a warning in runtime.

Warning: Functions are not valid as a React child. This may happen if you return a Component instead of <Component /> from render. Or maybe you meant to call this function rather than return it.
    at RescriptReactErrorBoundary

It is caused by the generated js representation is not fit to React API.

// with jsx ppx @react.component
function RescriptReactErrorBoundary(Props) {
  return getErrorBoundary(React.Component);
}

var make = RescriptReactErrorBoundary;

But, it should be

// without @react.component
var make = getErrorBoundary(React.Component);

children type incorrect for Fragment, StrictMode and Suspense

children for <>, React.Fragment, React.StrictMode and React.Suspense are typed as 'children instead of React.element.

This allows to compile incorrect code that breaks at runtime like

@react.component
let make = () => {
  <React.Suspense> 1 </React.Suspense>
}

publish 11.0 to npm?

Hi all
I see 11.0 tagged, but isnt up on npm.
Can that go up? Waiting on jsx4.something?

I notice that React.Context examples on website no longer compile in rescript-lang.org/try and wondering where to start.

Thanks!
A

Bindings to React modules are incompatible with node ESM

hello 👋

great work on the release!

I just found out that the new bindings, omitting the .js extension break when using node in ESM mode, as it tries to resolve to .mjs when unspecified. It currently breaks ReScript Pages (https://github.com/bloodyowl/rescript-pages/tree/upgrade-rescript-react) at runtime with the following error:

Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/Volumes/Dev/bloodyowl/rescript-pages/node_modules/react/jsx-runtime' imported from /Volumes/Dev/bloodyowl/rescript-pages/src/PagesServer.mjs
Did you mean to import react/jsx-runtime.js?
    at new NodeError (node:internal/errors:393:5)
    at finalizeResolution (node:internal/modules/esm/resolve:305:11)
    at moduleResolve (node:internal/modules/esm/resolve:866:10)
    at defaultResolve (node:internal/modules/esm/resolve:1074:11)
    at nextResolve (node:internal/modules/esm/loader:164:28)
    at ESMLoader.resolve (node:internal/modules/esm/loader:839:30)
    at ESMLoader.getModuleJob (node:internal/modules/esm/loader:426:18)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:76:40)
    at link (node:internal/modules/esm/module_job:75:36) {
  code: 'ERR_MODULE_NOT_FOUND'
}

and will most likely break any project in this configuration.

would you consider a PR adding the extensions back into the declarations?

Breaking change of key type

In JSX V3, the key type was optional. So, this expression was possible:

let key = Some("k")
<C ?key />

But, JSX v4 throws a type error.

this type is option<string> , expected string

ReactDOMServer.renderToString ... server.js not exported from react-dom

Hi Folks.
Just came across this problem in porting some existing js to rescript.
If i reimplement the renderToString bindings without the "js" suffix on the module, it seems to work fine.
Maybe a simple change to remove the suffix there?

Can make a PR if that seems reasonable

Thanks
Alex

Empty Fragments (<></>) no longer work

@react.component
let make = (~title: string) => {
    <div>
        {switch title {
        | "" => <></>
        | myTitle => <h2>{React.string(title)}</h2>
        }}
    </div>
}

After updating to rescript 11 and rescript react 11, empty fragments no longer work even if they have something inside them (like a react string). Replacing it with React.Fragment works.
It gives a slightly cryptic error message: Empty record literal {} should be type annotated or used in a record context.

Is this an issue with the JSX parser or did I miss something in the migration notes?

ReScript-aware `memo`

The current definition of React.memo is:

@module("react")
external memo: component<'props> => component<'props> = "memo"

which is incorrect. React.memo takes an equality function as an optional second param

https://react.dev/reference/react/memo

memo(SomeComponent, arePropsEqual?)

Fortunately, this can be easily fixed without breaking


Customizing the second argument is rare in regular JS/TS projects, but not in ReScript.

ReScript's powerful type system represents boxed objects at runtime. Ironically, this makes memo almost useless in ReScript projects, since the default for memo compares shallow equality.

E.g. Playground

Users can easily make deep-equality function

let equal = \"="
// this is confusing btw...

generates

import * as Caml_obj from "./stdlib/caml_obj.js";

var equal = Caml_obj.equal;

However the deep-equal implementation is usually not what React users want. This will be a huge overhead when dealing with data that is not a persistent structure.

Assuming the user still wants the shallow-equal, we can try a much more optimized solution. The idea is simple, making recursive shallow-equal, using well-known structures.

builtin shallowEqual function in React
// https://github.com/facebook/react/blob/857ee8c/packages/shared/shallowEqual.js#L18

// `is` and `hasOwnProperty` are polyfill of `Object` static methods
function shallowEqual(objA: mixed, objB: mixed): boolean {
  if (is(objA, objB)) {
    return true;
  }

  if (
    typeof objA !== 'object' ||
    objA === null ||
    typeof objB !== 'object' ||
    objB === null
  ) {
    return false;
  }

  const keysA = Object.keys(objA);
  const keysB = Object.keys(objB);

  if (keysA.length !== keysB.length) {
    return false;
  }

  // Test for A's keys different from B.
  for (let i = 0; i < keysA.length; i++) {
    const currentKey = keysA[i];
    if (
      !hasOwnProperty.call(objB, currentKey) ||
      // $FlowFixMe[incompatible-use] lost refinement of `objB`
      !is(objA[currentKey], objB[currentKey])
    ) {
      return false;
    }
  }

  return true;
}
modified for ReScript outputs
function shallowEqualPolyvar(objA: polyvar, objB: polyvar) {
  if (objA.NAME !== objB.NAME) {
    return false;
  }
  return shallowEqual(objA, objB);
}

function shallowEqualVariant(objA: variant, objB: variant) {
  // Ok... this should be done by the compiler
  if (objA.TAG !== objB.TAG) {
    return false;
  }
  return shallowEqual(objA._0, objB._0)
}

function shallowEqual(objA: mixed, objB: mixed): boolean {
  if (is(objA, objB)) {
    return true;
  }

  if (
    typeof objA !== 'object' ||
    objA === null ||
    typeof objB !== 'object' ||
    objB === null
  ) {
    return false;
  }
  
  // We cannot skip check because there is no guarantee objs are record.
  // Or maybe we can make separate function for it.

  // isPolyvar should be provided by the compiler
  const isObjAPolyvar = isPolyvar(objA)
  const isObjBPolyvar = isPolyvar(objB)
  if (isObjAPolyvar !== isObjBPolyvar) {
    return false;
  } else if (isObjAPolyvar) {
    return shallowEqualPolyvar(objA, objB);
  }

  // isVariant should be provided by the compiler
  const isObjAVariant = isVariant(objA)
  const isObjBVariant = isVariant(objB)
  if (isObjAVariant !== isObjBVariant) {
    return false;
  } else if (isObjAVariant) {
    return shallowEqualVariant(objA, objB)
  }

  const keysA = Object.keys(objA);
  const keysB = Object.keys(objB);

  if (keysA.length !== keysB.length) {
    return false;
  }

  // Test for A's keys different from B.
  for (let i = 0; i < keysA.length; i++) {
    const currentKey = keysA[i];
    if (
      !hasOwnProperty.call(objB, currentKey) ||
      !is(objA[currentKey], objB[currentKey])
    ) {
      return false;
    }
  }

  return true;
}

it seems like compiler support is needed first 😅

Transform HTML entities to unicode

The Babel JSX compiler converts HTML entities into the unicode characters they represent. In ReScript, we have to use the actual unicode directly. For some characters, like &nbsp; this isn't always convenient.

Would it be possible for the React PPX to do the same transformation that Babel does? See their entity map for reference: https://github.com/babel/babel/blob/b3e2bcda73dea7d68b4c82bfabb92acb11b1ed90/packages/babel-parser/src/plugins/jsx/xhtml.js

Babel example

Input

let f = () => <div>&nbsp;</div>;

output

let f = () => /*#__PURE__*/React.createElement("div", null, "\xA0");

ReScript example

Input

let f = () => <div> {React.string("&nbsp;")} </div>

Output

function f(param) {
  return React.createElement("div", undefined, "&nbsp;");
}

Note that "&nbsp; will render as-is, not as an actual nonbreaking space character.

Polyvariant attributes: to bump or not to bump

First of all, thank you for this project. I think that it should be mentioned in reason-react repo and website, your work deserves much more attention from outside 😊 .

Said that, I was interested to open a PR for something I wanted for a long time: support for polyvariant attributes. However, just a few days ago rescript 9.0 came out, and because its intrinsic major breaking change, they decided to make the syntax clearer.
The question is: should I make a PR for the 8.3 version using the older syntax or should I bump bs-platform to 9 and use the new syntax?
Obiously, if you intend to postpone this feature for future releases, just close the issue for now without worries.
Thanks again for your work!

Split into multiple packages?

  1. With JSX4 bringing breaking changes, the JSX3 bindings have been moved into a separate namespace ReactV3. I was wondering if this ReactV3 namespace shouldn't better be provided by some compatibility package.
  2. @rescript/react currently includes bindings for both react and react-dom and also has both as peer and dev dependencies. However, not every React project is also using React DOM. E.g. React Native projects aren't. So IMHO react-dom bindings should go into their own package.
  3. #33 mentions the idea to split out ReScriptReactRouter into a separate package.

If we did all that, we'd end up with something like

  • @rescript/react
  • @rescript/react-dom
  • @rescript/react-jsx3-compat
  • @rescript/rescript-react-router (or just rescript-react-router?)

@mattdamon108 @cristianoc What do you think? How would such a split affect the PPX?

Can I use async in event handler?

I want to use it to add the async in the onClick handler. But the compiler wants a unit return type.

let onClick = async _evt => {
  open Fetch
  open Promise

  let url = "https://jsonplaceholder.typicode.com/todos/1"

  let res = await fetch(url)->then(Response.json)
}

...

<button onClick> {"get todos"->React.string} </button>
This has type: JsxEvent.Mouse.t => promise<unit>
Somewhere wanted: JsxEvent.Mouse.t => unit

The incompatible parts:
  promise<unit> vs unit

So, I tried to change the return type unit type to promise<unit> in the ReactDom file in my local node_modules.

/* Mouse events */
@optional
onClick: ReactEvent.Mouse.t => unit,

    /* Mouse events */
    @optional
    onClick: ReactEvent.Mouse.t => promise<unit>,

But, It complains still.

I thought a simple workaround was just using Obj.magic like

<button onClick={Obj.magic(onClick)}> {"get todos"->React.string} </button>

and, it worked.

Is there any good workaround for this situation?

Use async event handler is not good or just not dealt with binding?

v1.0 Release Tasks

The v1.0 release will introduce more potential breaking changes, due to a new ppx release.

  • Discuss upcoming changes / upgrade strategy (see RFC post)
  • Finish react-ppx v4 integration (see PR)
  • Clean up the Apis for v1 usage (simplify some other modules, like ReactTestUtils)
  • Write migration guide from v0.10 to v1.0

JSX Changes

This is a cross-repo change and so I want to have a place here to comment/get feedback from folks.

In particular I want to remember to take a look at all of the issues/prs tagged html attribute change #38 will land since it's a bug but still needs to be ported over.

React@18 support

Context

React 18 is in RC and will soon be released:

reactwg/react-18#112

Updates

  • Deprecate ReactDOM.render
  • ReactDOM.Experimental.createRootReactDOM.createRoot
  • ReactDOM.Experimental.createBlockingRoot
  • ReactDOM.Experimental.rootReactDOM.Root.t
  • ReactDOM.Experimental.renderReactDOM.Root.render
  • ReactDOM.Root.unmount
  • React.useDeferredValue
  • React.useInsertionEffect{,0,1,2,3,4,5,6,7}
  • React.useSyncExternalStore
  • React.useId

Support react@canary release

React have plans to add new valid element/node type, hooks and APIs as react canary released.
I summarized that required for upcoming react canary things. Can we support these?

New React hooks and APIs are:

  • use: (promise<'value> | context<'value>) => 'value
    • I would suggest new type valueContainer<'value> to express above as they defined value container in RFC.
    • TypeScript type binding
  • cache: 'value => 'value
    • next.js docs
    • TypeScript: export function cache<CachedFunction extends Function>(fn: CachedFunction): CachedFunction
  • useTransition (already bound, just ignore)
  • useDeferredValue (already bound, just ignore)
  • startTransition: ((. unit => unit) => unit)

New ReactDOM hooks and APIs are:

Client Action Function Support: string | (formData: FormData) => unit

  • <button formAction={(formData) => { ... }} />
  • <form action={(formData) => { ... }} />

Async component:

rescript input:

type user = {id: string, name: string}
let fetchUserById = async (userId) => {
  {
    id: userId,
    name: Js.Float.toStringWithRadix(Js.Math.random(), ~radix=16),
  }
}

@react.component
let make = async (~userId) => {
  let user = await fetchUserById(userId)
  <div> {React.string(user.name)} </div>
}

Async component JS output expectation:

import * as JsxRuntime from "react/jsx-runtime";
async function fetchUserById(userId) {
  return { id: userId, name: Math.random().toString(16) };
}
async function Playground(props) {
  var user = await fetchUserById(props.userId);
  return JsxRuntime.jsx("div", { children: user.name });
}
var make = Playground;
export { fetchUserById, make };

New valid node:

Promise node:

type user = {id: string, name: string}
let fetchUserById = async (userId) => {
  {
    id: userId,
    name: Js.Float.toStringWithRadix(Js.Math.random(), ~radix=16),
  }
}

let fetchUserNameById = async (userId) => {
  let user = await fetchUserById(userId)
  user.name
}

@react.component
let make = (~userId) => {
  let userName = fetchUserNameById(userId)
  <React.Suspense>
    {React.promise(userName)}
  </React.Suspense>
}

expect output:

import * as React from "react";
import * as JsxRuntime from "react/jsx-runtime";
async function fetchUserById(userId) {
  return { id: userId, name: Math.random().toString(16) };
}
async function fetchUserNameById(userId) {
  return (await fetchUserById(userId)).name;
}
function Playground(props) {
  var userName = fetchUserNameById(props.userId);
  return JsxRuntime.jsx(React.Suspense, { children: userName });
}
var make = Playground;
export { fetchUserById, fetchUserNameById, make };

React.Context node


thank you for reading this.

Be careful about peer dependency

Note npm@7 is more strict with peerDependencies, I do not have time to think about it yet, here are issues I found.

This package have 3 peer dependencies:

  "bs-platform": "^8.3.0",
   "react": "^16.8.1",
   "react-dom": "^16.8.1"

So, you will have an installation error (by default), if you have a different version of this package in your own package.json. For example, if I have [email protected] installed, here is the error message I got:

npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR! 
npm ERR! Found: [email protected]
npm ERR! node_modules/bs-platform
npm ERR!   dev bs-platform@"9.0.1" from the root project
npm ERR! 
npm ERR! Could not resolve dependency:
npm ERR! peer bs-platform@"^8.3.0" from @rescript/[email protected]
npm ERR! node_modules/@rescript/react
npm ERR!   @rescript/react@"^0.10.1" from the root project
npm ERR! 
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force, or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.
npm ERR! 
npm ERR! See /Users/hongbozhang/.npm/eresolve-report.txt for a full report.

The work around is using --legacy-peer-deps as suggested

Add support for loading prop on images

Hello! I want to be able to set an image to loading="lazy" but this dom prop does not exist. I can open a PR to add it, but I don't think I have the right permissions. Thanks!

Props overwritten when they have the same prefix followed by underscores

This rescript component:

@react.component
let make = (
  ~foo__one,
  ~foo__two,
) => {
  <div>
    {foo__one->React.string}
    {foo__two->React.string}
  </div>
}

Generates this javascript function:

function Playground(Props) {
  var foo__one = Props.foo;
  var foo__two = Props.foo;
  return React.createElement("div", undefined, foo__one, foo__two);
}

Notice that foo__one and foo__two are both assigned the value of Props.foo.
The result is that the value passed for ~foo__one get's rendered twice and ~foo_two is ignored.

It would be helpful if this at least generated a warning.

Checking backward compatibility with JSX PPX V4

This issue is only affected with JSX PPX V4.
Some of React components are disposed to be built error, e.g. React.Fragment, React.Suspense, etc. Because it is written without @react.component attribute, which is impossible to use in the self cycled module React.

module Fragment = {
  @obj
  external makeProps: (~children: element, ~key: 'key=?, unit) => {"children": element} = ""
  @module("react")
  external make: component<{
    "children": element,
  }> = "Fragment"
}

I think that it is better to rewrite those components with @react.component attribute for the future migration not only for V4. My initial suggestion is to make those components to the separated module, such as RescriptReact.Fragment(leave the original components there as they are for backward compatibility). How about it?

EDIT: There was similarly rewriting #47

Expose ReactDOM.Props.domProps separately and concat?

Hi All
I am trying to compactly wrap a native input using createDOMElementVariadic, since input props are expansive and who wants to repeat all that. I notice that createDOMElementVariadic takes domProps, but that domProps and props are both @deriving(abstract) in the same module, so the accessors for domProps are shadowed. Also, with the types being abstract I can't add props to an existing domProps.

How does a PR for separating domProps to its own module and providing a concat operator sound?

React imports do not use relative paths with es6-global

With "module": "es6-global" in my bsconfig.json, my imports look like this:

import * as React from "react";
import * as Js_exn from "../node_modules/rescript/lib/es6/js_exn.js";
import * as ReactDom from "react-dom";
import * as Belt_Option from "../node_modules/rescript/lib/es6/belt_Option.js";
import * as Caml_option from "../node_modules/rescript/lib/es6/caml_option.js";
import * as App$MyThing from "./App.mjs"

which causes this error message in my browser console:

Uncaught TypeError: Failed to resolve module specifier "react". Relative references must start with either "/", "./", or "../".

Implicit type conversion?

Hello,
I’m exploring rescript-react and noticed a peculiar behaviour. Here’s my test code:

module MyComponent = {
  @react.component
  let make = () => {
    let (value, setValue) = React.useState(_ => 0)
    <>
      <div> {React.string(string_of_int(value))} </div>
      <input
        onChange={evt => {
          let x = ReactEvent.Form.target(evt)["value"] // 1
          setValue(_ => x) // 2
        }}
      />
    </>
  }
}

What I noticed is that on the line marked with // 1 the type of x is 'a, but on line // 2 hovering over x shows the type int. Why is that? I would expect the compiler to ask me to decode the value of x.

Thank you in advance!

P.S.

Upgrading to @rescript/react is incompatible with most of my app’s dependencies based on reason/react

Some scripts that I use in my app are breaking. For example:

  1. rescript-recoil
  2. bs-reach
  3. re-formality

is there a way to fix this other than waiting for the third-party libs to catch up?

example of error

It's possible that your build is stale.
Try to clean the artifacts and build again?

Here's the original error message
The files /code/sobras/node_modules/rescript-recoil/lib/ocaml/recoil.cmi
and /code/sobras/node_modules/@rescript/react/lib/ocaml/react.cmi
make inconsistent assumptions over interface React

example 2

It's possible that your build is stale.
Try to clean the artifacts and build again?

Here's the original error message
The files /Users/jorgec/Downloads/code/sobras/node_modules/@rescript/react/lib/ocaml/react.cmi
and /Users/jorgec/Downloads/code/sobras/node_modules/re-formality/lib/ocaml/formality.cmi
make inconsistent assumptions over interface React

example 3

It's possible that your build is stale.
Try to clean the artifacts and build again?

Here's the original error message
The files /Users/jorgec/Downloads/code/sobras/node_modules/@rescript/react/lib/ocaml/reactDOMRe.cmi
and /Users/jorgec/Downloads/code/sobras/node_modules/bs-reach/lib/ocaml/slider-Reach.cmi
make inconsistent assumptions over interface React

Put JSX 4 PPX support functions into a separate module

Currently, the React module has the functions createElementWithKey and createElementVariadicWithKey.

In my understanding, these are helper functions required for the JSX 4 PPX, but are not meant to be used by a user of the React bindings.

I would therefore propose to move them to a separate module, something like ReactPPX4Support. What do you think @mattdamon108?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.