-
Notifications
You must be signed in to change notification settings - Fork 39
Remove Array JSX
"children" argument
#15
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
Conversation
Also some other things: - no more key warnings for normal usage - `React.Basic` no longer depends on `React.Basic.DOM` - displayName - rename `react` to `reactComponent` - add new `react` which behaves more like `React.Basic.DOM` components (simpler api for PureScript-only components by pre-applying `createElement`) Closes #14
Definitely changed more than I originally set out to, but a lot of the changes seemed to complement each other. |
codegen/index.js
Outdated
-> JSX | ||
${e} = ${voids.indexOf(e) >= 0 ? 'createElementNoChildren' : 'createElement'} "${e}" | ||
`).forEach((x) => console.log(x.replace(/^\n\ {4}/, '').replace(/\n\ {4}/g, '\n'))) | ||
${reserved.includes(e) ? `${e}_` : e} = createElement (unsafeCoerce "${e}") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The unsafeCoerce
converts the DOM string into a ReactComponent
, which they are as far as createElement
is concerned. DOM components are weird that way.
}; | ||
const reserved = ["module", "data", "type", "newtype", "class", "instance", "where", "derive", "if", "then", "else", "case", "of"]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we're using these as record labels, there's no need to escape keywords (at least in recent versions of PureScript).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They become function names though, like div
. The one that was giving me problems was data
. Apparently it's an HTML tag.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't realize data
was a html tag. None of the others listed in reserved
are html tags are they? @paf31 Was data
not causing a problem in the previous version of this script?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assumed I got a newer version of react-html-attributes
or something. It seemed safer to add everything to the reserved list than have to remember and go back later if type
or module
become elements.
src/React/Basic.js
Outdated
var React = require("react"); | ||
var KeyedContainer = React.Fragment || "div"; | ||
|
||
// Class polyfill |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The license might need updating if we include this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll look into it
src/React/Basic.js
Outdated
var KeyedContainer = React.Fragment || "div"; | ||
|
||
// Class polyfill | ||
var __extends = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the difference between using this and react-create-class
again?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Autobinding and mixins. If we do use create-react-class
we need to add it as a dependency and import it. I'm not able to find it on Github either, and it's much larger than this polyfill. Also from the perspective of someone who's never seen this library before and the first lines of the readme ask for an extra dependency they don't expect to need, I think it's an unnecessary obstacle/complication.
@@ -32,25 +29,57 @@ foreign import react_ | |||
-- | constructed using the helper functions provided by the `React.Basic.DOM` | |||
-- | module (and re-exported here). | |||
react |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find this API a little more confusing. If we're renaming things, I like reactComponent
for creating a ReactComponent
, but react
should just go away IMO, and if we want a function for creating JSX directly from a spec (did you have a use case in mind?) then we can probably find a new name for that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That function already exists (createElement
). The only difference is whether you use createElement
at the time of component definition (like the DOM module does) or in a render function. It's not necessary, but I do think it's more pleasant to use if you're writing lots of PS components.
, receiveProps: mkEffFn3 receiveProps | ||
, render: mkFn3 render | ||
} | ||
|
||
foreign import component_ :: forall props. Fn2 (ReactComponent props) props JSX | ||
-- | SetState uses an update function to modify the current state. | ||
type SetState state fx = (state -> state) -> Eff (react :: ReactFX | fx) Unit |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 for moving to state -> state
. I think this could let us build more interesting abstraction on top, without adding dependencies and complexity here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a good change. I was playing with this library this weekend and had state issues with the current approach because of react and batching. This solved the issue I ran into.
src/React/Basic.js
Outdated
}; | ||
|
||
exports.createElement_ = function(el, attrs) { | ||
return React.createElement.apply(null, [el, attrs].concat(attrs.children)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
attrs.children
might be undefined, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point 👍
src/React/Basic.purs
Outdated
component = runFn2 component_ | ||
createElement = runFn2 createElement_ | ||
|
||
foreign import keyed :: Array { key :: String, child :: JSX } -> JSX |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about using a homogeneous record for this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's much harder to construct in PS and slightly harder to destruct in JS. This is for dynamic lists, where you're mapping over some data to produce JSX.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I should add docs to this
src/React/Basic/DOM.purs
Outdated
@@ -7,7 +7,7 @@ | |||
|
|||
module React.Basic.DOM where | |||
|
|||
import React.Basic.DOM.Internal (createElement, createElementNoChildren) | |||
import React.Basic (createElement) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This reverses the dependencies which means we can't reexport things. I'd really like to be able to use a single qualified import of React.Basic
which is why I went with the internal module.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, I think it would be good to give a name to unsafeCoerce :: String -> ReactComponent
and then to use that, since that is actually a safe coercion if you consider ReactComponent
to mean "something I pass to createElement
".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, I'll add that function.
As for module dependencies, the convenience of reexporting locks this library into DOM-only React, when in reality the only the only DOM-specific code in this library is the DOM module. This structure allows alternate base components, like native (and native-web).
If the div
component was actually defined as a component instead of React having special support for strings-as-components, they would be imported from react-dom
, not react
. We might also want to add purescript-react-basic-dom
at some point with a React.Basic.DOM.Render
module. This DOM module could live in either one since it doesn't actually depend on the react-dom
library.
- Attach TypeScript license for use of polyfill - Remove `react` and rename `reactComponent` back to `react` - More general `key` implementations
src/React/Basic.js
Outdated
this.state = spec.initialState; | ||
return this; | ||
} | ||
__extends(Component, React.Component); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens if you leave this out, out of curiosity?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think it will work, but I can try later. It'd be the same as creating a class to use as a component in ES2015 without adding extends React.Component
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried this, which worked:
Component.prototype = Object.create(React.Component.prototype);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I almost went that route originally but I was worried there might be some other implementation detail of class
I wasn't aware of. I'm fine with using that instead though until we find a problem.
src/React/Basic.js
Outdated
}; | ||
|
||
exports.createElementKeyed_ = function(el, key, attrs) { | ||
var attrsClone = __shallowCopy(attrs) || {}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we not accept a record including a key
property here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but that seems harder to type in PS. Have an idea?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking of this:
createElementKeyed
:: forall props
. ReactComponent { | props }
-> { key :: String | props }
-> JSX
createElementKeyed = runFn2 createElementKeyed_
foreign import createElementKeyed_ :: forall props. Fn2 (ReactComponent { | props }) { key :: String | props } JSX
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh right, that makes sense. We'd also be able to just use createElement_
for its implementation as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Never mind, we need both implementations because of the warning about keys.
I don't know that I have any major complaints with these changes, but I think my personal preference is the current api of |
README.md
Outdated
example :: R.ReactComponent ExampleProps | ||
example = R.react | ||
example :: ReactComponent ExampleProps | ||
example = reactComponent |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks like it was changed back to react
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks!
Also some other things:
React.Basic
no longer depends onReact.Basic.DOM
react
toreactComponent
react
which behaves more likeReact.Basic.DOM
components(simpler api for PureScript-only components by pre-applying
createElement
)Closes #14