Skip to content
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 Documentation, subtle typos and syntactic details #165

Merged
merged 4 commits into from
Feb 22, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 61 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,7 @@ clock =
, color: "blue"
}
-- additional Props.*
]
[ ]
] []
```

#### Components with type class constraints re-mount on every render?
Expand Down Expand Up @@ -220,3 +219,63 @@ defined that specifies the type parameter with the type class contraint.
If the component using the ordered list knows that the items are of type
`Int`, the component can define `orderedListInt` as shown above, and use
it to render the ordered list instead of `orderedList`.


#### Understanding `Children`


In React, we see the `children` prop type from time to time, especially
when using `createElement`. This is an opaque data type, in which we can
coerce into an `Array`, but we cannot create. Usually, when you see a
`ReactClass` that features a `children :: Children` prop type, this
means that the component itself expects children to be supplied as an
argument to `createElement`, in the form of an `Array ReactElement`.

However, in some circumstances (like a `ContextConsumer`), the `children`
prop type might look different, like `children :: a -> ReactElement`.
In this case, it would be better to use `createLeafElement`, to supply
the children _directly through the props_, rather than as a separate
argument.

This also means that any leaf-like components should _not_ define a
`children :: Children` prop - this prop should be treated as the
_expectation_ of a children argument. In the clock example above, a
more proper specification might look like the following:

```purescript
module Clock (clockComponent) where

import React (ReactClass, SyntheticEventHandler)
import React.SyntheticEvent (SyntheticEvent)

foreign import clockComponent
:: ReactClass
{ format :: String
, className :: String
, onTick :: SyntheticEventHandler SyntheticEvent
}
```

```purescript
module Component where

import Prelude

import Effect.Uncurried (mkEffectFn1)

import React as React
import React.SyntheticEvent as Event

import Clock as Clock

clock :: React.ReactElement
clock =
React.createLeafElement Clock.clockComponent
{ format: "HH:mm:ss"
, className: "test-class-name"
, onTick: mkEffectFn1 $ \event -> do
Event.preventDefault event
-- etc.
pure unit
}
```
6 changes: 3 additions & 3 deletions src/React.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ function createClassWithDerivedState(classCtr) {
return function(getDerivedStateFromProps) {
return function(ctrFn) {
var Constructor = componentImpl(displayName)(ctrFn);
Constructor.getDerivedStateFromProps = function(a, b) { return getDerivedStateFromProps(a)(b) };
Constructor.getDerivedStateFromProps = function(a, b) { return getDerivedStateFromProps(a)(b); };
return Constructor;
};
};
Expand All @@ -77,7 +77,7 @@ exports.componentImpl = componentImpl;
exports.componentWithDerivedStateImpl = createClassWithDerivedState(componentImpl);

var pureComponentImpl = createClass(React.PureComponent);
exports.pureComponentImpl = pureComponentImpl
exports.pureComponentImpl = pureComponentImpl;
exports.pureComponentWithDerivedStateImpl = createClassWithDerivedState(pureComponentImpl);

exports.statelessComponent = function(x) { return x; };
Expand All @@ -91,7 +91,7 @@ function getProps(this_) {
}
exports.getProps = getProps;

exports.childrenToArray = React.Children.toArray
exports.childrenToArray = React.Children.toArray;

exports.childrenCount = React.Children.count;

Expand Down
9 changes: 6 additions & 3 deletions src/React.purs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ module React
, childrenCount
, class IsReactElement
, toElement
, fragment
, fragmentWithKey
, Context
, ContextProvider
Expand Down Expand Up @@ -186,7 +187,7 @@ instance reactPureComponentSpec ::
) =>
ReactPureComponentSpec props state snapshot given spec

-- | Creates a `ReactClass`` inherited from `React.Component`.
-- | Creates a `ReactClass` inherited from `React.Component`.
component :: forall props state snapshot given spec.
ReactComponentSpec (Record props) (Record state) snapshot given spec =>
String ->
Expand All @@ -203,7 +204,7 @@ componentWithDerivedState :: forall props state snapshot given spec.
ReactClass (Record props)
componentWithDerivedState = componentWithDerivedStateImpl

-- | Creates a `ReactClass`` inherited from `React.PureComponent`.
-- | Creates a `ReactClass` inherited from `React.PureComponent`.
pureComponent :: forall props state snapshot given spec.
ReactPureComponentSpec (Record props) (Record state) snapshot given spec =>
String ->
Expand Down Expand Up @@ -391,7 +392,9 @@ foreign import createElementImpl :: forall required given children.
foreign import createElementDynamicImpl :: forall required given children.
ReactClass required -> given -> Array children -> ReactElement

-- | Create an element from a React class that does not require children.
-- | Create an element from a React class that does not require children. Additionally it can be used
-- | when the children are represented /only/ through the `children` prop - for instance, a `ContextConsumer`
-- | would be turned into a `ReactElement` with `createLeafElement someContext.consumer { children: \x -> ... }`.
createLeafElement :: forall required given.
ReactPropFields required given =>
ReactClass { | required } ->
Expand Down