Module

React.Basic.Hooks

Package
purescript-react-basic-hooks
Repository
spicydonuts/purescript-react-basic-hooks

#Component Source

type Component props = Effect (props -> JSX)

A simple type alias to clean up component definitions.

#component Source

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 Source

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 Source

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 Source

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 Source

data ReactChildren :: forall k. k -> Typedata ReactChildren a

#reactChildrenToArray Source

#reactChildrenFromArray Source

#memo Source

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). Prefer memo' for more PureScript-friendldy behavior.

#memo' Source

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

Similar to memo but takes a function to compare previous and new props. For example:

mkMyComponent :: Effect (ReactComponent { id :: Int })
mkMyComponent =
  memo' eq do
    reactComponent "MyComponent" \{ id } -> React.do
      ...

#useState Source

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

#useState' Source

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

#UseState Source

data UseState t0 t1

#useEffect Source

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 Source

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 Source

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 Source

data UseEffect t0 t1

#useLayoutEffect Source

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 Source

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 Source

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 Source

data UseLayoutEffect t0 t1

#Reducer Source

newtype Reducer state action

#mkReducer Source

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 optimize rendering behavior.

#runReducer Source

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 Source

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

Use mkReducer to construct a reducer function.

#UseReducer Source

data UseReducer t0 t1 t2

#readRef Source

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

#readRefMaybe Source

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

#writeRef Source

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

#useRef Source

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

#UseRef Source

data UseRef t0 t1

#useContext Source

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

#UseContext Source

data UseContext t0 t1

#useEqCache Source

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 Source

data UseEqCache t0 t1

#useMemo Source

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 Source

data UseMemo t0 t1 t2

#useDebugValue Source

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

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

#UseDebugValue Source

data UseDebugValue t0 t1

#UnsafeReference Source

#displayName Source

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

#(/\) Source

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 (/\) Source

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 Source

data Ref t0

A React Ref, as created by React.createRef

#ReactContext Source

data ReactContext t0

#ReactComponent Source

data ReactComponent t0

Represents a traditional React component. Useful for JavaScript interop and FFI. For example:

foreign import ComponentRequiringJSHacks :: ReactComponent { someProp :: String }

See also: element, toReactComponent

#JSX Source

data JSX

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 Source

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

Create a provider JSX given a context value and children.

See also: createContext, consumer

#keyed Source

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 Source

fragment :: Array JSX -> JSX

Render an Array of children without a wrapping component.

See also: JSX

#empty Source

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 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.

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

#element Source

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 Source

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 Source

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

#contextConsumer Source

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

#consumer Source

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

#Render Source

newtype Render x y a

Render represents the effects allowed within a React component's body, i.e. during "render". This includes hooks and ends with returning JSX (see pure), but does not allow arbitrary side effects.

The x and y type arguments represent the stack of effects that this Render implements, with x being the stack at the start of this Render, and y the stack at the end.

See purescript-indexed-monad to understand how the order of the stack is enforced at the type level.

Instances

#Pure Source

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 Source

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

#Hook Source

type Hook :: (Type -> Type) -> Type -> Typetype 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 Source

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 Source

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 Source

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 Source

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 Source

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 (&) Source

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