Just published a video introduction on how to integrate Haxe into a React create-react-app workflow. Includes using benmerckx’s watch library for auto-compiling the Haxe code, and using haxiomic’s dts2hx library for generating Haxe externs from third-party react libraries. Brief introductions on how to use functional components including hooks, as well as class-based components - all in a typesafe manner.
Hey, nice! Definitely easier to get started with haxe + react this way
Couple notes:
You might want to check React.createRef() for easier refs (and don’t ignore null values sent to your ref callback, it usually means your component unmounted, and you don’t want to keep an outdated reference).
Also, careful with “type safety” here; you don’t really have it in several places (hooks, context, and even props on the jsx side).
It’s probably worth mentioning react-next for increased type safety in jsx (although I can’t fully comment on how far it goes these days).
As for hooks, I don’t see why they would not be typed. It is however true that the dependencies array is not statically checked, as it is with eslint/tslint in create-react-app’s setup. From my own experience, that’s not necessarily a down side though
thanks for this great tutorial but i have some problem using react.ReactComponent here are the error messages:
workspaces/shirase/apps/testreact/src-hx/import.hx:4: characters 8-28 : Type not found : react.ReactComponent
/workspaces/shirase/apps/testreact/src-hx/import.hx:5: characters 8-24 : Type not found : react.ReactMacro
/workspaces/shirase/apps/testreact/src-hx/import.hx:9: characters 8-23 : Type not found : szhin.ReactMenu
/workspaces/shirase/apps/testreact/src-hx/import.hx:10: characters 8-23 : Type not found : szhin.ReactMenu
/workspaces/shirase/apps/testreact/src-hx/import.hx:11: characters 8-23 : Type not found : szhin.ReactMenu
src-hx/Index.hx:4: characters 8-28 : Type not found : react.ReactComponent
src-hx/Index.hx:5: characters 8-24 : Type not found : react.ReactMacro
/workspaces/shirase/apps/testreact/src-hx/import.hx:4: characters 8-28 : Type not found : react.ReactComponent
/workspaces/shirase/apps/testreact/src-hx/import.hx:5: characters 8-24 : Type not found : react.ReactMacro
/workspaces/shirase/apps/testreact/src-hx/import.hx:9: characters 8-23 : Type not found : szhin.ReactMenu
/workspaces/shirase/apps/testreact/src-hx/import.hx:10: characters 8-23 : Type not found : szhin.ReactMenu
/workspaces/shirase/apps/testreact/src-hx/import.hx:11: characters 8-23 : Type not found : szhin.ReactMenu
src-hx/react/ReactHooks.hx:5: characters 8-19 : Type not found : react.React
src-hx/react/ReactHooks.hx:13: characters 40-55 : Type not found : ReactContext
It seems that something in the dts2hx process has changed, probably to a new version of @szhsin-react-menu, so that dts2hx now creates completel new react externs. Have a look into .haxlib/react/ folder, there’s a 17.0.27 foldler, probably created by dts2hx. That’s what’s causing the Type not found: react.ReactComponent problem, if I’m not mistaken…
You can switch back to the original haxelib version by changing the content of the text file .haxelib/react/.current to 1.12.0.
So that solves half of the problem - the szhsin externs won’t work now, because they are refering to the newer 17.0.27 version…
Creating externs manually for React components actually isn’t that hard. Here’s a quick example:
// ReactMenu.hx
// Drop this file into your your haxe project src folder
@:jsRequire('@szhsin/react-menu')
extern class ReactMenu {
static function useMenuState(?options:ReactMenuStateOptions):{
@:optional
var state:ReactMenuState;
dynamic function toggleMenu(?open:Bool):Void;
dynamic function endTransition():Void;
};
static final MenuButton:Dynamic;
static final Menu:Dynamic;
static final ControlledMenu:Dynamic;
static final SubMenu:Dynamic;
static final MenuItem:Dynamic;
static final FocusableItem:Dynamic;
static final MenuDivider:Dynamic;
static final MenuHeader:Dynamic;
static final MenuGroup:Dynamic;
static final MenuRadioGroup:Dynamic;
// static function applyHOC<H>(hoc:H):H;
// static function applyStatics<W>(sourceComponent:Dynamic):(w:W) -> W;
}
typedef ReactMenuStateOptions = {
@:optional
var initialMounted:Bool;
@:optional
var unmountOnClose:Bool;
@:optional
var transition:Dynamic;
@:optional
var transitionTimeout:Float;
};
typedef ReactMenuState = String;
I tried to compile this code in other computer but i got this error:
$haxe build.hxml
the error is
src-hx/Index.hx:10: characters 1-9 : Unexpected function
what should i do?
You need at least 4.2.0 to use module level functions. Before that version you need a class around your functions, which in this example will also need to be declared as static.
You can have a look at lix-pm, which helps to install and version your project dependencies : haxe version, libraries (from haxelib, github…). It allows your project to be portable across computers and through time because it locks the libs’ and haxe versions your required, and install them if needed.
Part of it is an “haxe installer”, so you can use the version you want for your project, without manually installing it globally or relying on your system’s packaged version. The readme describes well how to get started.