diff --git a/README.md b/README.md index dcb79ab..ed4aa6f 100644 --- a/README.md +++ b/README.md @@ -141,8 +141,7 @@ clock = , color: "blue" } -- additional Props.* - ] - [ ] + ] [] ``` #### Components with type class constraints re-mount on every render? @@ -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 + } +``` diff --git a/src/React.js b/src/React.js index db2c58b..91d4c45 100644 --- a/src/React.js +++ b/src/React.js @@ -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; }; }; @@ -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; }; @@ -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; diff --git a/src/React.purs b/src/React.purs index e7b2d0e..22f6c4a 100644 --- a/src/React.purs +++ b/src/React.purs @@ -58,6 +58,7 @@ module React , childrenCount , class IsReactElement , toElement + , fragment , fragmentWithKey , Context , ContextProvider @@ -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 -> @@ -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 -> @@ -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 } ->