Coder Social home page Coder Social logo

haxe-react's Introduction

Haxe React

TravisCI Build Status Haxelib Version Join the chat at https://gitter.im/haxe-react

A Haxe library offering externs and tool functions leveraging Haxe's excellent type system and compile time macros to offer a strongly typed language to work with the increasingly popular React library.

haxelib install react

What's included / not included

This library covers React core and ReactDOM. It does NOT cover: ReactAddOns, react-router or React Native.

We recommend looking into / contributing to the following efforts:

Application architecture examples

React doesn't enforce any specific application architecture; here are a few approaches:

Redux, a very popular new approach of Model-View-Intent architecture: global state object, following immutability principles, but the wiring has been re-imagined to use the best of Haxe:

MMVC, classic, battle tested, Model-View-Mediator with state of the art Dependency Injection:

Flux, inspired by Facebook's suggested architecture for React; this is a very quick PoC which probably won't scale well to complex apps, but it shows a good range of React features:

Support / discussions

If you have questions / issues, join haxe-react on Gitter.im

API

Most of the regular React API is integrated (non-JSX example):

import api.react.React;
import api.react.ReactDOM;

class App extends ReactComponent {

	static public function main() {
		ReactDOM.render(React.createElement(App), Browser.document.getElementById('app'));
	}

	public function new() {
		super();
	}

	override function render() {
		var cname = 'foo';
		return React.createElement('div', {className:cname}, [/*children*/]);
	}
}

Note that React.createElement strictly expects either a String, a Function, or a class extending ReactComponent. It includes when writing externs for 3rd party JS libraries you must specify extends:

@:jsRequire('react-redux', 'Provider')
extern class Provider extends react.ReactComponent { }

JSX

The Haxe compiler (and editors) doesn't allow to use exactly the JSX XML DSL, so we had to compromise a bit...

This library's take on JSX is to use a compile-time macro to parse JSX as a string to generate the same kind of code that Facebook's JSX, Babel and Typescript will generate.

Both classic JSX {} binding and Haxe string interpolation $var / ${expression} / <$Comp> are allowed. The advantage of string interpolation is Haxe editor supports for completion and code navigation.

Spread operator and complex expressions within curly braces are supported.

import api.react.React;
import api.react.ReactDOM;
import api.react.ReactMacro.jsx;

class App extends ReactComponent {

	static public function main() {
		ReactDOM.render(jsx('<App/>'), Browser.document.getElementById('app'));
	}

	public function new() {
		super();
	}

	override function render() {
		var cname = 'foo';
		return jsx('
			<div className=$cname>
				<App.statelessComponent style=${{margin:"10px"}}/>
				${/*children*/}
			</div>
		');
	}

	static function statelessComponent(props:Dynamic) {
		return jsx('<div {...props}/>');
	}
}

JSX Fragments

Fragments (React 16.2+) let you group a list of children without adding extra nodes to the DOM.

Two syntaxes are supported:

<Fragment>
    Text
    <span>more text</span>
    Still more text
</Fragment>

// or short syntax:
<>
    Text
    <span>more text</span>
    Still more text
</>

JSX gotchas

  1. JSX is not String magic! Do not concatenate Strings to construct the JSX expression

  2. Haxe's JSX parser is not "re-entrant"

    In JavaScript you can nest JSX inside curly-brace expressions:

    return (
        <div>{ isA ? <A/> : <B/> }</div>
    );

    However this isn't allowed in Haxe, so you must extract nested JSX into variables:

    var content = isA ? jsx('<A/>') : jsx('<B/>');
    return jsx('<div>{content}</div>');

Components strict typing

The default ReactComponent type is a shorthand for ReactComponentOf<Dynamic, Dynamic, Dynamic>, a fully untyped component.

To fully benefit from Haxe's strict typing you should look into extending a stricter base class:

typedef ReactComponentOfProps<TProps> = ReactComponentOf<TProps, Dynamic, Dynamic>;
typedef ReactComponentOfState<TState> = ReactComponentOf<Dynamic, TState, Dynamic>;
typedef ReactComponentOfRefs<TRefs> = ReactComponentOf<Dynamic, Dynamic, TRefs>;
typedef ReactComponentOfPropsAndState<TProps, TState> = ReactComponentOf<TProps, TState, Dynamic>;
typedef ReactComponentOfPropsAndRefs<TProps, TRefs> = ReactComponentOf<TProps, Dynamic, TRefs>;
typedef ReactComponentOfStateAndRefs<TState, TRefs> = ReactComponentOf<Dynamic, TState, TRefs>;

React JS dependency

There are 2 ways to link the React JS library:

Require method (default)

By default the library uses require('react') to reference React JS.

This means you are expected to use npm to install this dependency:

npm install react

and a second build step to generate the final JS file, for instance using browserify:

npm install browserify
browserify haxe-output.js -o final-output.js

(note that you can use watchify to automatically run this build step)

Global JS

The other common method is to download or reference the CDN files of React JS in your HTML page:

<script src="//cdnjs.cloudflare.com/ajax/libs/react/16.2.0/umd/react.development.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/react-dom/16.2.0/umd/react-dom.development.js"></script>

and don't forget to add the following Haxe define to your build command:

-D react_global

Look at samples/todoapp for an example of this approach.

JSX Optimizing Compiler

Inline ReactElements

By default, when building for release (eg. without -debug), calls to React.createElement are replaced by inline JS objects (if possible).

See: facebook/react#3228

// regular
return React.createElement('div', {key:'bar', className:'foo'});

// inlined (simplified)
return {$$typeof:Symbol.for('react.element'), type:'div', props:{className:'foo'}, key:'bar'}

This behaviour can be disabled using -D react_no_inline.

Optimization tools

Avoidable renders warning

Setting -D react_render_warning will enable runtime warnings for avoidable renders.

This will add a componentDidUpdate (or update the existing one) where a shallowCompare is done on current and previous props and state. If both did not change, a warning will be displayed in the console.

False positives can happen if your props are not flat, due to the shallowCompare.

haxe-react's People

Contributors

efimster avatar elsassph avatar francescoagati avatar gama11 avatar jasononeil avatar jozefchutka avatar kevinresol avatar klabz avatar markknol avatar piotjag avatar tomashubelbauer avatar

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.