-
Notifications
You must be signed in to change notification settings - Fork 38
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Better integration of HOC factories #18
Comments
Or... it should be up to the ReactRedux (or any other lib) extern to define its hoc factory metadata itself... That probably preferable as it would maybe allow a better checking from the compiler... |
Some cases HOCs would difficult to reconcile with Haxe I think.
The first step is to figure what Haxe code should be generated for such cases. Eg. if it's possible to write manually, then it can be generated using a macro - otherwise it's likely that it's not possible. |
Hi there! I do not understand all what you wrote... Maybe because I was not clear myself. I'll try to sumarize the issue: The HOC factories actually only inject logic/objects in the component props. No mixin here nor extension nor anything else... When you do
Yep, that makes sense to me. So, if we stick to the ReactRedux example, here is what I currently do (and it works of course): MyComp.hx:
App.hx
It would be great to have some nicer syntax that does not require to write this: Is it clear to you? How would you see this with a macro/metadata/... ? Note that the ReactRedux.connect factory is the most complex HOC factory I've seen until now. Usually, it's just a normal function that just takes your comp as parameter like this one:
Note also that we need a system that allows "hoc factory chaining" on a single comp (some comp need to be passed through several different HOC factories to let them get features from several libs). |
I hope you realize that That's the reason why the recommended pattern in JS is to completely replace I didn't check what Finally for the sake of exhaustivity, I've seen HOCs adding functions to the class prototype instead of extending the component with a new class. This is also pretty hard to support in typed languages. A pattern that seem to work is: class MyComp {
static public var Connect = ReactRedux.connect(mapStateToProps)(MyComp);
...
} Which you would use as: That is nicely compatible with Haxe and easy to write manually. Potentially you could come up with a macro generating such |
Gosh! Thanks for pointing this me out :s! ReactIntl.injectIntl() also returns a wrapping component... I believe it will be the case most of the time with HOC factories...
I have not seen that yet. Also is this compatible with ES6? I haven't learnt ES6 yet but given that mixins are not possible with ES6, I would suspect this way of designing HOC factories would not work with ES6... If that's the case, we could consider this use case of HOC factories to be invalid and thus not support it...
Yep, I agree it's the simplest and cleanest way so far... If it was just to generate this and nothing else, I think no macro is needed here... However, maybe we could think of a macro that would:
So that in only one statement (a metadata actually) we enforce the Redux additional props to the MyComp props and "connect" it... Or maybe that's not a good idea and it has not such a great value that it would require the pain of working on a macro for that... What do you think? |
You can still modify the prototype in ES6, and do mixins "manually". There just isn't a way using the
How do you know which props to add? I think you should just define those props as expected by your component even if it wasn't connected through redux. Generally you want to avoid defining new types - it's badly handled by IDEs unless they are indirectly accessed. |
@elsassph Maybe with the help of a custom js generator it'd be possible? It'd be pretty hardcore to do and maintain though. Not sure if worth it. |
A custom JS generator would make the redux |
I successfully use react-redux's class VisibleTodoList {
static function mapStateToProps(state) {
return {...}
}
static function mapDispatchToProps(dispatch) {
return {...}
}
static function __init__()
// kind of hack to assign something to a class, but works
untyped VisibleTodoList = js.Lib.require('react-redux').connect(mapStateToProps, mapDispatchToProps)(TodoList);
}
class TodoList extends ReactComponent {
override function render() {
return jsx('...');
}
} |
You can further improve it by writing some macros to insert the @:build(ReactReduxMacro.connect(TodoList))
class VisibleTodoList {
static function mapStateToProps(state) {
return {...}
}
static function mapDispatchToProps(dispatch) {
return {...}
}
}
class ReactReduxMacro {
public static function connect(e:Expr) {
var cls = Context.getLocalClass().get();
return Context.getBuildFields().concat([{
access: [AStatic],
name: '__init__',
kind: FFun({
args: [],
expr: macro untyped $i{cls.name} = js.Lib.require('react-redux').connect(mapStateToProps, mapDispatchToProps)($e),
ret: null,
}),
pos: Context.currentPos(),
}]);
}
} |
This is starting to be clever, but that isn't really a scalable pattern of you want to heavily use HOCs. |
What are the possible issues with this approach, seems to be fine if the end user is given the choice to either use the lower order component vs the higher order one in a Render. |
Any updates on |
Current recommended approach would be using @:jsxStatic(wrapped)
class VisibleTodoList {
static function mapStateToProps(state) {
return {...}
}
static function mapDispatchToProps(dispatch) {
return {...}
}
static final wrapped = js.Lib.require('react-redux').connect(TodoList, mapStateToProps, mapDispatchToProps);
} PS: it's better BTW to declare |
There are with react-next https://github.com/kLabz/haxe-react/blob/next/doc/wrapping-with-hoc.md |
Oh actually |
Copying everything from the link above up to |
Reorganised and completed the documentation about it - check the readme :) |
Nice, readme looks a lot better like that 👍 |
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:
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.
The text was updated successfully, but these errors were encountered: