React.Basic
- Package
- purescript-react-basic
- Repository
- lumihq/purescript-react-basic
#ComponentSpec Source
type ComponentSpec props state = (didMount :: Self props state -> Effect Unit, didUpdate :: Self props state -> { prevProps :: props, prevState :: state } -> Effect Unit, initialState :: state, render :: Self props state -> JSX, shouldUpdate :: Self props state -> { nextProps :: props, nextState :: state } -> Boolean, willUnmount :: Self props state -> Effect Unit)
ComponentSpec
represents a React-Basic component implementation.
These are the properties your component definition may override
with specific implementations. None are required to be overridden, unless
an overridden function interacts with state
, in which case initialState
is required (the compiler enforces this).
initialState
- The component's starting state.
- Avoid mirroring prop values in state.
render
- Takes a current snapshot of the component (
Self
) and converts it to renderableJSX
.
- Takes a current snapshot of the component (
didMount
- The React component's
componentDidMount
lifecycle. Useful for initiating an action on first mount, such as fetching data from a server.
- The React component's
shouldUpdate
- Can be useful for performance optimizations. Rarely necessary.
didUpdate
- The React component's
componentDidUpdate
lifecycle. Rarely necessary.
- The React component's
willUnmount
- The React component's
componentWillUnmount
lifecycle. Any subscriptions or timers created indidMount
ordidUpdate
should be disposed of here.
- The React component's
The component spec is generally not exported from your component
module and this type is rarely used explicitly. make
will validate whether
your component's internal types line up.
For example:
component :: Component Props
component = createComponent "Counter"
type Props =
{ label :: String
}
counter :: Props -> JSX
counter = make component
{ initialState: { counter: 0 }
, render: \self ->
R.button
{ onClick: capture_ $ self.setState \s -> s { counter + 1 }
, children: [ R.text (self.props.label <> ": " <> show self.state.counter) ]
}
}
This example component overrides initialState
and render
.
Note: A ComponentSpec
is not a valid React component by itself. If you would like to use
a React-Basic component from JavaScript, use toReactComponent
.
See also: Component
, ComponentSpec
, make
, makeStateless
#createComponent Source
createComponent :: forall props. String -> Component props
Creates a Component
with a given Display Name.
The resulting component spec is usually given the simplified Component
type:
component :: Component Props
component = createComponent "Counter"
This function should be used at the module level and considered side effecting.
This is because React uses referential equality when deciding whether a new
JSX
tree is a valid update or if it needs to be replaced entirely
(expensive and clears component state lower in the tree).
Note: A specific type for the props in Component props
should always be chosen at this point.
It's technically possible to declare the component with forall props. Component props
but doing so is unsafe. Leaving the prop type open allows the use of a single Component
definition in multiple React-Basic components that may have different prop types. Because
component lifecycles are managed by React, it becomes possible for incompatible prop values to
be passed by React into lifecycle functions.
Note: A Component
is not a valid React component by itself. If you would like to use
a React-Basic component from JavaScript, use toReactComponent
.
See also: Component
, make
, makeStateless
#Component Source
data Component props
Opaque component information for internal use.
Note: Never define a component with
a less specific type for props
than its associated ComponentSpec
and make
calls, as this can lead to unsafe interactions with React's lifecycle management.
For the curious: This is the "class" React will use to render and
identify the component. It receives the ComponentSpec
as a prop and knows
how to defer behavior to it. It requires very specific props and is not useful by
itself from JavaScript. For JavaScript interop, see toReactComponent
.
#Self Source
type Self props state = { instance_ :: ReactComponentInstance props state, props :: props, setState :: (state -> state) -> Effect Unit, setStateThen :: (state -> state) -> Effect Unit -> Effect Unit, state :: state }
Self
represents the component instance at a particular point in time.
props
- A snapshot of
props
taken when thisSelf
was created.
- A snapshot of
state
- A snapshot of
state
taken when thisSelf
was created.
- A snapshot of
setState
- Update the component's state using the given function.
setStateThen
- Update the component's state using the given function. The given effects are performed after any resulting rerenders are completed. Be careful to avoid using stale props or state in the effect callback. Use
readProps
orreadState
to aquire the latest values.
- Update the component's state using the given function. The given effects are performed after any resulting rerenders are completed. Be careful to avoid using stale props or state in the effect callback. Use
instance_
- Unsafe escape hatch to the underlying component instance (
this
in the JavaScript React paradigm). Avoid as much as possible, but it's still frequently better than rewriting an entire component in JavaScript.
- Unsafe escape hatch to the underlying component instance (
See also: ComponentSpec
, send
, capture
, readProps
, readState
#StateUpdate Source
data StateUpdate props state
Describes a state update for use with runUpdate
.
See also: runUpdate
Constructors
NoUpdate
Update state
SideEffects (Self props state -> Effect Unit)
UpdateAndSideEffects state (Self props state -> Effect Unit)
#make Source
make :: forall state props spec_ spec. Union spec spec_ (ComponentSpec props state) => Component props -> { initialState :: state, render :: Self props state -> JSX | spec } -> props -> JSX
Turn a Component
and ComponentSpec
into a usable render function.
This is where you will want to provide customized implementations:
component :: Component Props
component = createComponent "Counter"
type Props =
{ label :: String
}
counter :: Props -> JSX
counter = make component
{ initialState: { counter: 0 }
, render: \self ->
R.button
{ onClick: capture_ $ self.setState \s -> s { counter = s.counter + 1 }
, children: [ R.text (self.props.label <> ": " <> show self.state.counter) ]
}
}
See also: makeStateless
, createComponent
, Component
, ComponentSpec
#makeStateless Source
makeStateless :: forall props. Component props -> (props -> JSX) -> props -> JSX
Makes stateless component definition slightly less verbose:
component :: Component Props
component = createComponent "Xyz"
myComponent :: Props -> JSX
myComponent = makeStateless component \props -> JSX
Note: The only difference between a stateless React-Basic component and
a plain props -> JSX
function is the presense of the component name
in React's dev tools and error stacks. It's just a conceptual boundary.
If this isn't important simply write a props -> JSX
function.
See also: make
, createComponent
, Component
, ComponentSpec
#JSX Source
data JSX :: Type
Represents rendered React VDOM (the result of calling React.createElement
in JavaScript).
JSX
is a Monoid
:
append
- Merge two
JSX
nodes usingReact.Fragment
.
- Merge two
mempty
- The
empty
node; renders nothing.
- The
Hint: Many useful utility functions already exist for Monoids. For example,
guard
can be used to conditionally render a subtree of components.
Instances
#element Source
element :: forall props. ReactComponent (Record props) -> Record props -> JSX
Create a JSX
node from a ReactComponent
, by providing the props.
This function is for non-React-Basic React components, such as those imported from FFI.
See also: ReactComponent
, elementKeyed
#elementKeyed Source
elementKeyed :: forall props. ReactComponent (Record props) -> { key :: String | props } -> JSX
Create a JSX
node from a ReactComponent
, by providing the props and a key.
This function is for non-React-Basic React components, such as those imported from FFI.
See also: ReactComponent
, element
, React's documentation regarding the special key
prop
#displayNameFromComponent Source
displayNameFromComponent :: forall props. Component props -> String
Retrieve the Display Name from a ComponentSpec
. Useful for debugging and improving
error messages in logs.
See also: displayNameFromSelf
, createComponent
#displayNameFromSelf Source
displayNameFromSelf :: forall state props. Self props state -> String
Retrieve the Display Name from a Self
. Useful for debugging and improving
error messages in logs.
See also: displayNameFromComponent
, createComponent
#ReactComponent Source
data ReactComponent :: Type -> Type
Represents a traditional React component. Useful for JavaScript interop and FFI. For example:
foreign import ComponentRequiringJSHacks :: ReactComponent { someProp :: String }
See also: element
, toReactComponent
#ReactComponentInstance Source
data ReactComponentInstance :: Type -> Type -> Type
An opaque representation of a React component's instance (this
in the JavaScript
React paradigm). It exists as an escape hatch to unsafe behavior. Use it with
caution.
#toReactComponent Source
toReactComponent :: forall state props jsProps spec_ spec. Union spec spec_ (ComponentSpec props state) => (Record jsProps -> props) -> Component props -> { render :: Self props state -> JSX | spec } -> ReactComponent (Record jsProps)
Convert a React-Basic ComponentSpec
to a JavaScript-friendly React component.
This function should only be used for JS interop and not normal React-Basic usage.
Note: Like createComponent
, toReactComponent
is side effecting in that
it creates a "class" React will see as unique each time it's called. Lift
any usage up to the module level, usage in render
or any other function,
and applying any type classes to the props
.
See also: ReactComponent