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 props hooks. 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 props hooks. 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 children props hooks. 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 r props hooks. 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

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

#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 :: Type -> Type -> Type

#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 and Effect which removes the listener.

#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 :: Type -> Type -> Type

#useLayoutEffect Source

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

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

#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

#useReducer Source

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

#UseReducer Source

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

#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

#reactChildrenFromArray Source

#reactChildrenToArray Source

#useRef Source

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

#UseRef Source

data UseRef :: Type -> Type -> Type

#useContext Source

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

#UseContext Source

data UseContext :: Type -> Type -> Type

#useMemo Source

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

Use this hook to memoize a value based on a set of deps. This is useful when you need to take advantage of memo and need to pass referentially equal values to a child component. This is purely a performance optimization and shouldn't change the behavior of your component.

If building a value of a is expensive, try useLazy.

#UseMemo Source

data UseMemo :: Type -> Type -> Type

#useLazy Source

useLazy :: forall a deps. Eq deps => deps -> (Unit -> a) -> Hook (UseLazy deps a) a

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

#UseLazy Source

data UseLazy :: Type -> Type -> Type -> Type

#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 :: Type -> Type -> Type

#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 :: Type -> Type

A React Ref, as created by React.createRef

#ReactContext Source

#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

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

render self =
  R.div_
  [ R.button
    { onClick: capture_ $ self.setState \s -> s { counter = s.counter + 1 }
    , children: [ R.text "Tick!" ]
    }
  , provider countContext self.state.counter
    [ consumer countContext \counter ->
       [ R.text $ "Ticks: " <> (show counter)
       ]
    ]
  ]

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.

#Hook Source

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 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 a newHook. 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 keys as they use Eq and a reorder would allow React to pass incorrect types into the eq function!

#discard Source

discard :: forall m z y x b a. 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 a newHook oldHook hooks. 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 m z y x b a. IxBind m => m x y a -> (a -> m y z b) -> m x z b

Exported for use with qualified-do syntax