Module

React.Basic.Hooks

#Component

type Component props = Effect (props -> JSX)

A simple type alias to clean up component definitions.

#component

component :: forall hooks props. String -> (props -> Render Unit hooks JSX) -> Component props

Create a component function given a display name and render function. Creating components is effectful because React uses the function instance as the component's "identity" or "type". Components should be created during a bootstrap phase and not within component lifecycles or render functions.

#reactComponent

reactComponent :: forall hooks props. Lacks "children" props => Lacks "key" props => Lacks "ref" props => String -> (Record props -> Render Unit hooks JSX) -> Effect (ReactComponent (Record props))

Create a React component given a display name and render function. Creating components is effectful because React uses the function instance as the component's "identity" or "type". Components should be created during a bootstrap phase and not within component lifecycles or render functions. See componentWithChildren if you need to use the children prop.

#reactComponentWithChildren

reactComponentWithChildren :: forall hooks props children. Lacks "key" props => Lacks "ref" props => String -> ({ children :: ReactChildren children | props } -> Render Unit hooks JSX) -> Effect (ReactComponent { children :: ReactChildren children | props })

Create a React component given a display name and render function. This is the same as component but allows the use of the children prop.

#reactComponentFromHook

reactComponentFromHook :: forall hooks props r. Lacks "children" props => Lacks "key" props => Lacks "ref" props => String -> ({ render :: r -> JSX | props } -> Hook hooks r) -> Effect (ReactComponent { render :: r -> JSX | props })

Convert a hook to a render-prop component. The value returned from the hook will be passed to the render prop, a function from that value to JSX.

This function is useful for consuming a hook within a non-hook component.

#ReactChildren

#reactChildrenToArray

#reactChildrenFromArray

#memo

memo :: forall props. Effect (ReactComponent props) -> Effect (ReactComponent props)

Prevents a component from re-rendering if its new props are referentially equal to its old props (not value-based equality -- this is due to the underlying React implementation).

#useState

useState :: forall state. state -> Hook (UseState state) (state /\ ((state -> state) -> Effect Unit))

#useState'

useState' :: forall state. state -> Hook (UseState state) (state /\ (state -> Effect Unit))

#UseState

data UseState :: Type -> Type -> Type

#useEffect

useEffect :: forall deps. Eq deps => deps -> Effect (Effect Unit) -> Hook (UseEffect deps) Unit

Runs the given effect when the component is mounted and any time the given dependencies change. The effect should return its cleanup function. For example, if the effect registers a global event listener, it should return an Effect which removes the listener.

useEffect deps do
  timeoutId <- setTimeout 1000 (logShow deps)
  pure (clearTimeout timeoutId)

If no cleanup is needed, use pure (pure unit) or pure mempty to return a no-op Effect

useEffect deps do
  logShow deps
  pure mempty

#useEffectOnce

useEffectOnce :: Effect (Effect Unit) -> Hook (UseEffect Unit) Unit

Like useEffect, but the effect is only performed a single time per component instance. Prefer useEffect with a proper dependency list whenever possible!

#useEffectAlways

useEffectAlways :: Effect (Effect Unit) -> Hook (UseEffect Unit) Unit

Like useEffect, but the effect is performed on every render. Prefer useEffect with a proper dependency list whenever possible!

#UseEffect

data UseEffect :: Type -> Type -> Type

#useLayoutEffect

useLayoutEffect :: forall deps. Eq deps => deps -> Effect (Effect Unit) -> Hook (UseLayoutEffect deps) Unit

Like useEffect, but the effect is performed synchronously after the browser has calculated layout. Useful for reading properties from the DOM that are not available before layout, such as element sizes and positions. Prefer useEffect whenever possible to avoid blocking browser painting.

#useLayoutEffectOnce

useLayoutEffectOnce :: Effect (Effect Unit) -> Hook (UseLayoutEffect Unit) Unit

Like useLayoutEffect, but the effect is only performed a single time per component instance. Prefer useLayoutEffect with a proper dependency list whenever possible!

#useLayoutEffectAlways

useLayoutEffectAlways :: Effect (Effect Unit) -> Hook (UseLayoutEffect Unit) Unit

Like useLayoutEffect, but the effect is performed on every render. Prefer useLayoutEffect with a proper dependency list whenever possible!

#UseLayoutEffect

#Reducer

newtype Reducer state action

#mkReducer

mkReducer :: forall state action. (state -> action -> state) -> Effect (Reducer state action)

Creating reducer functions for React is effectful because React uses the function instance's reference to optimise rendering behavior.

#runReducer

runReducer :: forall state action. Reducer state action -> state -> action -> state

Run a wrapped Reducer function as a normal function (like runFn2). Useful for testing, simulating actions, or building more complicated hooks on top of useReducer

#useReducer

useReducer :: forall state action. state -> Reducer state action -> Hook (UseReducer state action) (state /\ (action -> Effect Unit))

Use mkReducer to construct a reducer function.

#UseReducer

data UseReducer :: Type -> Type -> Type -> Type

#readRef

readRef :: forall a. Ref a -> Effect a

#readRefMaybe

readRefMaybe :: forall a. Ref (Nullable a) -> Effect (Maybe a)

#writeRef

writeRef :: forall a. Ref a -> a -> Effect Unit

#useRef

useRef :: forall a. a -> Hook (UseRef a) (Ref a)

#UseRef

data UseRef :: Type -> Type -> Type

#useContext

useContext :: forall a. ReactContext a -> Hook (UseContext a) a

#UseContext

data UseContext :: Type -> Type -> Type

#useEqCache

useEqCache :: forall a. Eq a => a -> Hook (UseEqCache a) a

Cache an instance of a value, replacing it when eq returns false.

This is a low-level performance optimization tool. It can be useful for optimizing a component's props for use with memo, where JavaScript instance equality matters.

#UseEqCache

data UseEqCache :: Type -> Type -> Type

#useMemo

useMemo :: forall deps a. Eq deps => deps -> (Unit -> a) -> Hook (UseMemo deps a) a

Lazily compute a value. The result is cached until the deps change.

#UseMemo

data UseMemo :: Type -> Type -> Type -> Type

#useDebugValue

useDebugValue :: forall a. a -> (a -> String) -> Hook (UseDebugValue a) Unit

Use this hook to display a label for custom hooks in React DevTools

#UseDebugValue

data UseDebugValue :: Type -> Type -> Type

#UnsafeReference

#displayName

displayName :: forall props. ReactComponent props -> String

Retrieve the Display Name from a ReactComponent. Useful for debugging and improving error messages in logs.

See also: component

Re-exports from Data.Tuple.Nested

#(/\)

Operator alias for Data.Tuple.Tuple (right-associative / precedence 6)

Shorthand for constructing n-tuples as nested pairs. a /\ b /\ c /\ d /\ unit becomes Tuple a (Tuple b (Tuple c (Tuple d unit)))

#type (/\)

Operator alias for Data.Tuple.Tuple (right-associative / precedence 6)

Shorthand for constructing n-tuple types as nested pairs. forall a b c d. a /\ b /\ c /\ d /\ Unit becomes forall a b c d. Tuple a (Tuple b (Tuple c (Tuple d Unit)))

Re-exports from React.Basic

#Ref

data Ref :: Type -> Type

A React Ref, as created by React.createRef

#ReactContext

#ReactComponent

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

#JSX

data JSX :: Type

Represents rendered React VDOM (the result of calling React.createElement in JavaScript).

JSX is a Monoid:

  • append
    • Merge two JSX nodes using React.Fragment.
  • mempty
    • The empty node; renders nothing.

Hint: Many useful utility functions already exist for Monoids. For example, guard can be used to conditionally render a subtree of components.

Instances

#provider

provider :: forall a. ReactContext a -> a -> Array JSX -> JSX

Create a provider JSX given a context value and children.

See also: createContext, consumer

#keyed

keyed :: String -> JSX -> JSX

Apply a React key to a subtree. React-Basic usually hides React's warning about using key props on components in an Array, but keys are still important for any dynamic lists of child components.

See also: React's documentation regarding the special key prop

#fragment

fragment :: Array JSX -> JSX

Render an Array of children without a wrapping component.

See also: JSX

#empty

empty :: JSX

An empty JSX node. This is often useful when you would like to conditionally show something, but you don't want to (or can't) modify the children prop on the parent node.

See also: JSX, Monoid guard

#elementKeyed

elementKeyed :: forall props. ReactComponent (Record props) -> { key :: String | props } -> JSX

Create a JSX node from a ReactComponent, by providing the props and a key.

See also: ReactComponent, element, React's documentation regarding the special key prop

#element

element :: forall props. ReactComponent (Record props) -> Record props -> JSX

Create a JSX node from a ReactComponent, by providing the props.

See also: ReactComponent, elementKeyed

#createContext

createContext :: forall a. a -> Effect (ReactContext a)

Create a ReactContext given a default value. Use provider and consumer to provide and consume context values. Alternatively, use contextProvider and contextConsumer directly if a ReactComponent is required for interop.

See also: provider, consumer, React's documentation regarding Context

#contextProvider

contextProvider :: forall a. ReactContext a -> ReactComponent { children :: Array JSX, value :: a }

#contextConsumer

contextConsumer :: forall a. ReactContext a -> ReactComponent { children :: a -> Array JSX }

#consumer

consumer :: forall a. ReactContext a -> (a -> Array JSX) -> JSX

Create a consumer JSX from a context value to children.

See also: createContext, producer

Re-exports from React.Basic.Hooks.Internal

#Pure

type Pure a = forall hooks. Render hooks hooks a

Type alias used to lift otherwise pure functionality into the Render type. Not commonly used.

#HookApply

type HookApply hooks (newHook :: Type -> Type) = newHook hooks

#Hook

type Hook (newHook :: Type -> Type) a = forall hooks. Render hooks (newHook hooks) a

Type alias for Render representing a hook.

The newHook argument is a type constructor which takes a set of existing effects and generates a type with a new set of effects (produced by this hook) stacked on top.

#unsafeRenderEffect

unsafeRenderEffect :: forall a. Effect a -> Pure a

Promote an arbitrary Effect to a Pure render effect.

This is unsafe because it allows arbitrary effects to be performed during a render, which may cause them to be run many times by React. You should almost always prefer useEffect!

#unsafeHook

unsafeHook :: forall newHook a. Effect a -> Hook newHook a

Promote an arbitrary Effect to a Hook.

This is unsafe because it allows arbitrary effects to be performed during a render, which may cause them to be run many times by React. This function is primarily for constructing new hooks using the FFI. If you just want to alias a safe hook's effects, prefer coerceHook.

It's also unsafe because the author of the hook type (the newHook type variable used here) MUST contain all relevant types. For example, UseState has a phantom type to track the type of the value contained. useEffect tracks the type used as the deps. useAff tracks both the deps and the resulting response's type. Forgetting to do this allows the consumer to reorder hook effects. If useState didn't track the return type the following extremely unsafe code would be allowed:

React.do
  if xyz then
    _ <- useState 0
    useState Nothing
  else
    s <- useState Nothing
    _ <- useState 0
    pure s
  ...

The same applies to deps in these examples as they use Eq and a reorder would allow React to pass incorrect types into the eq function!

#discard

discard :: forall a b x y z m. IxBind m => m x y a -> (a -> m y z b) -> m x z b

Exported for use with qualified-do syntax

#coerceHook

coerceHook :: forall hooks oldHook newHook a. Newtype newHook oldHook => Render hooks oldHook a -> Render hooks newHook a

Rename/alias a chain of hooks. Useful for exposing a single "clean" type when creating a hook to improve error messages and hide implementation details, particularly for libraries hiding internal info.

For example, the following alias is technically correct but when inspecting types or error messages the alias is expanded to the full original type and UseAff is never seen:

type UseAff deps a hooks
  = UseEffect deps (UseState (Result a) hooks)

useAff :: ... -> Hook (UseAff deps a) (Result a)
useAff deps aff = React.do
  ...

coerceHook allows the same code to safely export a newtype instead, hiding the internal implementation:

newtype UseAff deps a hooks
  = UseAff (UseEffect deps (UseState (Result a) hooks))

derive instance ntUseAff :: Newtype (UseAff deps a hooks) _

useAff :: ... -> Hook (UseAff deps a) (Result a)
useAff deps aff = coerceHook React.do
  ...

#bind

bind :: forall a b x y z m. IxBind m => m x y a -> (a -> m y z b) -> m x z b

Exported for use with qualified-do syntax

#type (&)

Operator alias for React.Basic.Hooks.Internal.HookApply (left-associative / precedence 0)

Applies a new hook to a hook chain, with the innermost hook as the left argument. This allows hook chains to be written in reverse order, aligning them with the order they appear when actually used in do-notation.

type UseCustomHook hooks = UseEffect String (UseState Int hooks)
type UseCustomHook' = UseState Int & UseEffect String

Modules