massive-oss / haxe-react Goto Github PK
View Code? Open in Web Editor NEWReact JS applications development using the Haxe language
React JS applications development using the Haxe language
When using existing react components, setDisplayName
is trying to generate field for extern class.
extern class ExternComponent extends ReactComponent {}
This gives me Extern non-inline variables may not be initialized
Can be avoided by if (inClass.isExtern) return null;
in setDisplayName
Hi,
First, great work with the lib. I'm getting into React and adding Haxe to the mix was something that was in the back of my head for some time, thanks for buidling and sharing this lib!
I'm curious about the following limitation:
You can't use functions (and thus factories) for stateless rendering. We're looking into this.
Do you mind providing a code example in the README depicting it? Also a short text explaining why it isn't possible with Haxe (and any possible workarounds) would be nice.
Thanks!
Thanks!
The parameters provided to setState must contain all the fields defined in TState
. Is it possible to override the type (or create another type) with macro to make all fields optional (for the setState function parameter only)?
Two workarounds for now:
setState(untyped {key:value});
), but this defeats the purpose of using haxe's type systemreturn jsx('<h2>Messages</h2><ul>$messages</ul>');
This is not valid React code, because React currently doesn't support returning multiple elements from the render method: facebook/react#2127
I think the macro should issue a warning where there is an attempt to return multiple elements. It could point the developer in the direction of wrapping the elements into a wrapper div
or something like that.
I am not sure I can provide a PR for this until I learn a little more Haxe so I'm just letting it be known for now.
Orange box here. I think it starts with React 15.5
I am not particularly sure if I am talking the right thing. But seems that react's createElement
will try to copy some props from the type's static var defaultProps
if a key doesn't exists. But our macro's inline mode doesn't seem to do that, causing some breakages on components that rely on it.
FYI, I have been experimenting JSX syntax highlighting inside Haxe code in Atom (see screenshot below). It both works with jsx('<something>')
(ie. haxe-react) and @jsx '<something>'
constructs.
For now, the code is on a language-haxe
fork (where I am working on improving the grammar in general, even though it is at exploration stage for now): https://github.com/jeremyfa/language-haxe
I thought some people around there might be interested about this.
hi,
reading this article https://reactjsnews.com/how-to-make-your-react-apps-10x-faster i have see that react can process object literals for template.
This have some performance,beacuse instead of calling createElement we can simple return the object literal created from createElement at compile time when the macro jsx works.
we could add a flag like -D react-fast-jsx to make retrun object literals from jsx macro instead of React.createElement
Also babel has introduce this new features
`
Babel 5.8.24 introduces Inlining React elements: The optimisation.react.inlineElements transform converts JSX elements to object literals like {type: 'div', props: ...} instead of calls to React.createElement . This should only be enabled in production, since it disables some development warnings/checks.
•Babel 5.8.24 introduces Constant hoisting for React elements: The optimisation.react.constantElements transform hoists element creation to the top level for subtrees that are fully static, which reduces calls to React.createElement and the resulting allocations. More importantly, it tells React that the subtree hasn’t changed so React can completely skip it when reconciling. This should only be enabled in production, since it disables some development warnings/checks.
`
React addons seem to be available only as packages so far...
I'm trying to use the ReactCSSTransitionGroup addon.
What I've done so far is defining a haxe extern with the @:jsRequire metadata:
package api.react.addon;
@:jsRequire("react-addons-css-transition-group")
extern class ReactCSSTransitionGroup
{
public static var transitionName : String;
public static var transitionEnterTimeout : Int;
public static var transitionLeaveTimeout : Int;
// ...
}
In my app code, I use it like I would with any other React component:
// ...
override function render() {
return jsx('
<div className="app">
<ReactCSSTransitionGroup transitionName="page" transitionEnterTimeout={500} transitionLeaveTimeout={300} >
{createPages()}
</ReactCSSTransitionGroup>
</div>
');
}
// ...
That doesn't work. It crashes at runtime with the following error:
Uncaught ReferenceError: require is not defined
console.undefined.log @ Type.hx:197
(anonymous function) @ ReactMacro.hx:121
Using more and more react js libraries like react-redux, react-intl, ... I face more and more the concept of Higher order component factories. This concept consist of wrapping your components to add it more features usually via props. It's done by exposing/exporting the result of a factory function that has been given your component class as parameters: for example here.
Another more complexe example is the ReactRedux.connect factory with can take more params.
While this is already implementable with haxe and haxe-react, I think we could had some metadata to expose directly the result of a HOC factory of component right in the same file as the component implementation itself. Something like:
typedef MyCompProps = {
// (...)
}
@:hoc("myFactory" /*, other params ? */)
class MyComp extends ReactComponentOf<MyCompProps, Dynamic, Dynamic> {
// (...)
}
We should also probably allow the @:hoc metada to be added several times on the same Component class...
In ES6, it seems we already have such a metadata feature for HOC factories: here is a es6 version use of the ReactRedux.connect factory.
And with javascript, we can (and usually do so) export the "factored" component in the same class file as the component class itself.
jsx('<div>& ×</div>')
generates React.createElement("div",null,"& &times;")
Actual jsx generates React.createElement("div",null,"& ×")
I was wondering why the package name is api.react
and not just react
? It seems to me that the api
intermediate package is not providing anything useful except noise in the code. At best I would just use the package name react
(just like here or there) and at worst use react.api
instead of api.react
to have at least everything grouped into a common react
package. I guess that your use of the api
namespace might be related to the way you organize your packages internally, but I believe it would be best kept simple and as internal-naming-convention-agnostic as possible, especially for a library as popular as React!
Anyway, that's a lot of text for a rather minor issue ;)
It's good to see some activity around Haxe for the React library (and looking forward to see the updated jsx parser 👍 ).
I named one of my component Loading
. In some of my other components where I'm using it, the haxe compilation sometimes generates things like this:
React.createElement("loading",null)
Instead of :
React.createElement(my_package_Loading,null)
The odd thing is that it does not generate this everywhere I use it.
I've just updated my haxe-react (I was still using a version from April) and now, because of this:
typedef CreateElementType = haxe.extern.EitherType<haxe.extern.EitherType<String, haxe.Constraints.Function>, Class<ReactComponent>>;
I cannot use extern classes like this for example:
@:jsRequire('react-redux', 'Provider')
extern class Provider { }
// ...
return jsx('
<Provider store={store}>
<Application />
</Provider>
');
It seems the JSX macro now enforces elements to be either Strings, functions or classes extended ReactComponent...
Is there any solution to declare an extern class as extending ReactComponent ? Or should I write wrapping Haxe React component for every external component I want to use?
Does this work with react-native?
I have warning like this #text cannot appear as a child of <tbody>
when run this simple app https://gist.github.com/meerfolk/c29d5d85983376fdde5fb623fd35ab23. In ReactDevTool a see this one http://prntscr.com/dul6pl
haxe 3.4.0-rc1
react 1.1.2
I need the mixins feature to use the ReactIntl lib.
I suppose we are subject to the same limitation as ES6 here?
E.g. jsx('<img style={{margin:0}}>')
This should be achievable by properly matching the close braces
https://facebook.github.io/react/docs/jsx-spread.html
It is useful in PanResponder
Is there a way to import css then use it?
E.g. one example I'm working with does this:
import styles from './InfiniteLoader.example.css'
Then refers to the CSS later on in JSX:
className={styles.List}
Is this possible (or even desirable) in haxe-react?
I wanted to use external jsx for instead of inline, with compiletime macro:
class Main {
public static function main() {
AppRegistry.registerComponent('TestReactNative', function() return App);
}
}
@:expose('App')
class App extends ReactComponent{
function new(props) {
super(props);
state = {
scene: 0
}
}
override function render() {
function goto(i) setState({scene: i});
return switch state.scene {
default:
jsx(CompileTime.readFile("jsx/Home.jsx"));
}
}
}
Home.jsx:
<WebView
source={{uri: 'https://github.com/facebook/react-native'}}
style={{marginTop: 20}}
>
</WebView>
but I got this error when compile:
/usr/local/lib/haxe/std/haxe/macro/ExprTools.hx:289: characters 11-16 : Unsupported expression: { expr => ECall({ expr => EField({ expr => EConst(CIdent(CompileTime)), pos => #pos(src/Main.hx:35: characters 20-31) },interpolateFile), pos => #pos(src/Main.hx:35: characters 20-47) },[{ expr => EConst(CString(jsx/Home.jsx)), pos => #pos(src/Main.hx:35: characters 48-62) }]), pos => #pos(src/Main.hx:35: characters 20-63) }
/Volumes/Work/develop/hx/libs/react/git/src/lib/react/ReactMacro.hx:27: characters 19-43 : Called from
src/Main.hx:35: characters 16-64 : Called from
How can I use external jsx with RNhaxe, if I can?
thanks
var b = jsx('<em>bbb</em>');
var a = jsx('<div><span>a</span> / {b}</div>'
Results in React.createElement("div",null,React.createElement("span",null,"a"),"/ ",b);
In actual jsx it's React.createElement("div",null,React.createElement("span",null,"a")," / ",b);
Notice lack of first space in "/ "
Hi !
It's really great to have the props, state and refs typed: ReactComponentOf<Dynamic, TState, TRefs>;
.
Maybe we could type the context too ? With something like this: ReactComponentOf<Dynamic, TState, TRefs, TContext>;
?
In api.react.ReactComponentOf it would look like this:
// (...)
extern class ReactComponentOf<TProps, TState, TRefs, TContext>
{
static var defaultProps:Dynamic;
static var contextTypes:Dynamic;
var props(default, null):TProps;
var state(default, null):TState;
var context(default, null):TContext;
(...)
Just getting starting with react and haxe, but I'm hitting a jsx compilation issue I can't seem to fix no matter how I rearrange and tweak the jsx.
I've labeled line 82 that the compiler complains about:
return jsx('
<InfiniteLoader
isRowLoaded={isRowLoaded}
loadMoreRows={loadMoreRows}
rowCount={rowCount}
>
{({ onRowsRendered, registerChild }) => (
<List
82: ref={registerChild}
onRowsRendered={onRowsRendered}
rowRenderer={rowRenderer}
{...otherProps}
/>
)}
</InfiniteLoader>
');
Gives this error:
src/example/todo/view/GalleryView.hx:82: lines 82-99 : Invalid JSX: Expected "
Any ideas?
Hi,
this is the content chrome dev tools see on the url http://localhost/devel/bin/ after copying the whole bin tree into the apache document root - no errors on the console:
Hi !
I've just identified a bug that were pretty sneaky: if you have a node in your jsx code with more that 15 children, the jsx macro will crash with the following error: haxe-react/src/lib/api/react/ReactMacro.hx:98: characters 15-54 : Too many arguments
Here is a sample render
component function that can lead to this issue:
override function render() {
return jsx('
<div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
');
}
I think that come from the definition of this method in api.react.React
:
public static function createElement(type:Dynamic, ?attrs:Dynamic,
?child1:Dynamic, ?child2:Dynamic, ?child3:Dynamic, ?child4:Dynamic, ?child5:Dynamic,
?child6:Dynamic, ?child7:Dynamic, ?child8:Dynamic, ?child9:Dynamic, ?child10:Dynamic,
?child11:Dynamic, ?child12:Dynamic, ?child13:Dynamic, ?child14:Dynamic, ?child15:Dynamic):ReactComponent;
That could be changed to this:
public static function createElement(type:Dynamic, ?attrs:Dynamic,
?children:haxe.extern.Rest<Dynamic>):ReactComponent;
But with this, it still do not compile:
haxe-react/src/lib/api/react/ReactMacro.hx:98: characters 15-54 : api.react.ReactComponent should be Null<haxe.extern.Rest<Dynamic>>
haxe-react/src/lib/api/react/ReactMacro.hx:98: characters 15-54 : api.react.ReactComponentOf<Dynamic, Dynamic, Dynamic> should be Null<haxe.extern.Rest<Dynamic>>
haxe-react/src/lib/api/react/ReactMacro.hx:98: characters 15-54 : api.react.ReactComponentOf<Dynamic, Dynamic, Dynamic> should be haxe.extern.Rest<Dynamic>
haxe-react/src/lib/api/react/ReactMacro.hx:98: characters 15-54 : For optional function argument 'children'
Do you see anything that could be done to make it accept a limitless number of children ?
jsx('<div>foo</div><div>bar</div>')
generates return React.createElement("div",null,"foo");
React's jsx fails with SyntaxError: embedded: Adjacent JSX elements must be wrapped in an enclosing tag
Hi,
i'am try to use compiletime lib for load external file. But there is a macro conflict i think.
with this code
return jsx( CompileTime.interpolateFile('a.txt'));
i get
C:\HaxeToolkit\haxe\std/haxe/macro/ExprTools.hx:286: characters 11-16 : Unsupported expression: { expr => ECall({ expr => EField({ expr => EConst(CIdent(CompileTime)), pos => #pos(src/Main.hx:60: characters 20-31) },interpolateFile), pos => #pos(src/Main.hx:60: characters 20-47) },[{ expr => EConst(CString(a.txt)), pos => #pos(src/Main.hx:60: characters 48-55) }]), pos => #pos(src/Main.hx:60: characters 20-56) }
This,
isn't a real bug of haxe-react but a bug of some distributions of haxe. Some cases of regular expression in haxe aren't supported.
In my case i have found this compiler error on my computer
Main.hx:11: lines 11-19 : Invalid JSX: Unsupported escaped char '{'
It seems that in the latest react version, the React.Component constructor and other React.Component methods like componentWillReceiveProps
can take a context
argument as parameter. Example here: https://github.com/reactjs/react-router/blob/c41309b3cd5ef5bf7e4b6e5219f0aba110557c7a/examples/animations/app.js#L22-L62
Right now this is now possible with haxe react... Is it just a matter or extending externs or is it more than that ?
Follow up to #49
Case 1: typo not detected
jsx('<div onClick={function() tracee(0)}></div>');
// doesn't catch typo. output `tracee(0)` as is
Case 2: types not referenced
// data/Data.hx
enum Data {
Video;
Photo;
}
// Main.hx
import data.Data;
return jsx('<div onClick={function() return Media}></div>');
// output `return Media` as is, but should be something like `return data_Data.Media`
jsx('
<div>
<p>Paragraph</p>
<div/>
');
The above code is unclosed, but parsed as if it is closed with an extra </div>
This cause some hard-to-notice bug when there are some typos (just as in the case above it should be </div>
instead of <div/>
)
This is just to let you know that I've started a github repo with externs for common React addons and libs there: https://github.com/tokomlabs/haxe-react-addons
This is definitively Work In Progress and many of them are just a @jsrequire call to the right lib path.
Bu if you have externs to share or if you'd like to start from there and add contributions, you are all very welcome.
I post this because of the TODO that is in the README of this repo:
TODO Externs for common. add-ons and react-router.
jsx('<button disabled>foo</button>');
This gives me Invalid JSX: Expected =
, when react itself can handle jsx like that. Easy to work around, but confusing at first.
https://github.com/massiveinteractive/haxe-react/blob/5c397e5/src/lib/api/react/ReactMacro.hx#L209
Here, the untyped
makes the function arguments untyped, it ignores typo or anything.
Can be fixed by wrapping a parenthesis: return macro (untyped api.react.React._createElement)($a{args});
But fundamentally why does the untyped
exist at all?
I'm looking at some different styles of JSX syntax and haven't been able to adapt haxe-react's JSX to support this conditional syntax.
Is this a supported syntax? I suspect that the JSX macro parser has limits that I'm running into?
This simple structure works, the expression results in either 'online' or 'offline' returned as a string
${ AuthenticationService.isLoggedIn() ? ('online') : ('offline')}
But am unable to return conditional elements - the entire expression is treated as string
${ AuthenticationService.isLoggedIn() ? (<span>online<span/>) : (<span>offline<span/>)}
Here's the relevant JSX syntax I'm working to implement
<div>
{isLoggedIn ? (
<LogoutButton onClick={this.handleLogoutClick} />
) : (
<LoginButton onClick={this.handleLoginClick} />
)}
</div>
I've just updated to libneko2 from PPA and now I get this error on any PCData element in jsx.
It come from ~/([^{]+|\{[^}]+\})/g
regexp in ReactMacro.parseJsxNode
Works nice in ~/([^{]+|{[^}]+})/g
form (notice lack of backslashes), but I don't know if this is proper PCRE and/or compatible with all Haxe platforms.
and ReactPropTypes to PropTypes (and others...)
That is more consistent with the original library and makes copy-pasting from JS easier.
We can typedef ReactCompoent = react.Component
to provide backward compatibility.
Obviously they are incorrect because haxe classes with packages like that should be generated as api_react_React
or api_react_ReactComponentOf
.
I guess there are somewhere in the code that wrote untyped api.react.React
so the compiler just generated them as-is.
I see this problem after the object-literal branch being merged.
TL;DR: setState
should also accept TState->TProps->TState
as argument
So I've been using this for a little while and gotten 1 or 2 apps working with it. But I've come to a situation - I want to use emoji in my current project and have to parse the content (which works fine). The library for emoji is a react-native one but I believe this is an issue? with jsx()
rather than native export.
private function parseEmoji(content:String):Dynamic {
var match:EReg = ~/:([a-z0-9_]+):/g;
if (content != null) {
content = match.replace(content, '<Emoji name="$1" />');
}
return content;
}
So that would give me something like :coffee: test emoji
to <Emoji name="coffee" />
which then becomes valid jsx syntax. When returning the code I then do
var emojify = this.parseEmoji(":coffee: test emoji");
var content = jsx('<Text style={styles.content}>$emojify</Text>');
but instead of parsing the $emojify
as jsx code, it would print it literally as the replacement
(<Emoji name="coffee" /> test emoji
). Is there a way around this?
React.__spread
is deprecated and should not be used. Use Object.assign
directly or another helper function with similar semantics.
Object.assign can be polyfilled so that should probably be documented.
Haxe type system should allow for more efficient compile-time resolution of spreads, instead of using Object.assign
at run-time.
This is the render
method of a component:
override function render() {
var sv = "some value";
return jsx('
<div className="page ${sv}">
${sv}
</div>
');
}
gives:
<div class="page {sv}" data-reactid=".0.$0">
<span data-reactid=".0.$0.0">some value</span>
</div>
I'm getting this warning at runtime if I define a getInitialState method in my React components:
Warning: getInitialState was defined on AppView, a plain JavaScript class. This is only supported for classes created using React.createClass. Did you mean to define a state property instead?
So I guess we should set this.state right in the constructor ?
That may be useful to document briefly all the deltas with using Rect with and without Haxe...
Hi
I tried the todo sample (https://github.com/massiveinteractive/haxe-react/tree/master/samples/todoapp)
Got this message when building app:
src/view/TodoApp.hx:38: lines 38-47 : Invalid JSX: Expected =
Hi, I'm checking out/learning react for first time. I'm excited I can use Haxe for this 😄
Question: I wonder if it is needed/preferred to have the statics in TodoActions, or how would this be solved otherwise?
Especially this one https://github.com/massiveinteractive/haxe-react/blob/master/samples/todoapp/src/view/TodoApp.hx#L63
I'm struggling with using React addons components with haxe-react.
The problem is that most react addons are distributed as npm packages. They usually contains var React = require('react')
statements which makes browserify including react in the output file (I did not find a way to exclude it from the output file).
On the other side, haxe-react seems to work only when React is used not as an npm package, but rather included via a script tag in the html page header.
The problem with this is that there can be only one React included at a time. If not, we get the following error at runtime:
Uncaught Error: Invariant Violation: addComponentAsRefTo(...): Only a ReactOwner can have refs. You might be adding a ref to a component that was not created inside a component's `render` method, or you have multiple copies of React loaded (details: https://fb.me/react-refs-must-have-owner).
If then I remove the script tags that import react and react-dom, I get of course this, as my compile haxe-react code does not find React:
Uncaught ReferenceError: React is not defined
As it seems that react components are distributed as npm packages only, the way would be to make haxe-react work with an npm version of React. How can we do that ?
"Hoists element creation to the top level for subtrees that are fully static, which reduces call to React.createElement
and the resulting allocations. More importantly, it tells React that the subtree hasn't changed so React can completely skip it when reconciling."
cf. http://babeljs.io/docs/plugins/transform-react-constant-elements/
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.