redraw

Types

Default Node in Redraw. In Redraw, A component can be of three shapes: “components”, accepting props and children, “elements”, accepting props, like <img> tags, and “standalone” components, accepting nothing. Use respectively component, element or standalone to create one of them.

pub type Component

Pass data without props drilling.
Documentation

pub type Context(a)

Main error type. Currently only used in conjuction with Context related functions.

pub type Error {
  ExistingContext(name: String)
  UnknownContext(name: String)
  DevelopmentOnly
  OwnerStackUnavailable
}

Constructors

  • ExistingContext(name: String)

    Error returned from create_context_. Context with the corresponding name already exists.

  • UnknownContext(name: String)

    Error returned from get_context. Context with the corresponding name does not exists.

  • DevelopmentOnly

    Error returned from capture_owner_stack. capture_owner_stack can only be used in development, and you’re not in development anymore.

  • OwnerStackUnavailable

    Error returned from capture_owner_stack. capture_owner_stack can sometimes return null, when the stack is unavailable.

A Ref is a mutable data stored in React, persisted across renders. They allow to keep track of a DOM node, a component data, or to store a mutable variable in the component, outside of every component lifecycle.
Documentation

pub type Ref(a)
pub type Suspense {
  Suspense(fallback: Component)
}

Constructors

Values

pub fn act(
  act_fn: fn() -> promise.Promise(Nil),
) -> promise.Promise(Nil)

Test helper to apply pending React updates before making assertions.
Documentation

pub fn capture_owner_stack() -> Result(String, Error)

Reads the current Owner Stack in development and returns it as a string if available.

Owner Stacks are available in

  • Component render
  • Effects (e.g. use_effect)
  • React’s event handlers (e.g. button([a.on_click(fn (_) {...})]))
  • React error handlers (React Root options onCaughtError, onRecoverableError, and onUncaughtError)

If no Owner Stack is available, null is returned (see Troubleshooting: The Owner Stack is null).

Owner Stacks are only available in development. captureOwnerStack will always return null outside of development.

Documentation

pub fn component(
  name name: String,
  render render: fn(props, children) -> Component,
) -> fn(props, children) -> Component

Create a Redraw component, with a name, and a render function. render will accept props, and a list of children.

pub fn context(
  name: String,
  default_value: fn() -> a,
) -> Context(a)

context emulates classic Context usage in React. Instead of calling create_context and get_context, it’s possible to simply call context, which will get or create the context directly, and allows to write code as if Context is globally available. context also tries to preserve type-checking at most. context.default_value is lazily evaluated, meaning no additional computations will ever be run.

import redraw

const context_name = "MyContextName"

pub type MyContext {
  MyContext(count: Int, set_count: fn (Int) -> Nil)
}

fn default_value() {
  let count = 0
  les set_count = fn (_) { Nil }
  MyContext(count:)
}

pub fn provider() {
  use _, children <- redraw.component()
  let context = redraw.context(context_name, default_value)
  let #(count, set_count) = redraw.use_state(0)
  redraw.provider(context, MyContext(count:, set_count:), children)
}

pub fn use_my_context() {
  let context = redraw.context(context_name, default_value)
  redraw.use_context(context)
}

context should never fail, but it can be wrong if you use an already used name.

pub fn create_context(
  name: String,
  default_value: a,
) -> Result(Context(a), Error)

Create a context that components can provide or read. Each context is referenced by its name, a little bit like actors in OTP (if you’re familiar with Erlang). Because Gleam cannot execute code outside of main function, creating a context should do some side-effect at startup.

In traditional React code, Context usage is usually written like this.

import * as react from 'react'

// Create your Context in a side-effectful way.
const MyContext = react.createContext(defaultValue)

// Create your own provider, wrapping your context.
export function MyProvider(props) {
  return <MyContext.Provider>{props.children}</MyContext.Provider>
}

// Create your own hook, to simplify usage of your context.
export function useMyContext() {
  return react.useContext(MyContext)
}

To simplify and mimic that usage, Redraw wraps Context creation with some caching, to emulate a similar behaviour.

import redraw

const context_name = "MyContextName"

pub fn my_provider(children) {
  let assert Ok(context) = redraw.create_context(context_name, default_value)
  redraw.provider(context, value, children)
}

pub fn use_my_context() {
  let assert Ok(context) = redraw.get_context(context_name)
  redraw.use_context(context)
}

Be careful, create_context fails if the Context is already defined. Choose a full qualified name, hard to overlap with inattention. If you want to get a Context in an idempotent way, take a look at context().

Documentation

pub fn element(
  name name: String,
  render render: fn(props) -> Component,
) -> fn(props) -> Component

Create a Redraw Element, with a name, and a render function. Keep in mind this component does not accept children as second argument.

pub fn fragment(children: List(Component)) -> Component

Fragment allow to group children, without creating a node in the DOM.
Documentation

pub fn get_context(name: String) -> Result(Context(a), Error)

Get a context. Because of FFI, get_context breaks the type-checker. It should be considered as unsafe code. As a library author, never exposes your context and expect users will call get_context themselves, but rather exposes a use_my_context() function, handling the type-checking for the user.

import redraw

pub type MyContext {
  MyContext(value: Int)
}

/// `use_context` returns `Context(a)`, should it can be safely returned as
/// `Context(MyContext)`.
pub fn use_my_context() -> redraw.Context(MyContext) {
  let context = case redraw.get_context("MyContextName") {
    // Context has been found in the context cache, use it as desired.
    Ok(context) -> context
    // Context has not been found. It means the user did not initialised it.
    Error(_) -> panic as "Unitialised context."
  }
  redraw.use_context(context)
}
pub fn get_current(from ref: Ref(a)) -> a

Get the current value of a ref.

pub fn keyed(
  element: fn(List(Component)) -> Component,
  content: List(#(String, Component)),
) -> Component

Redraw does not support passing key element to components in an easy way like React does. To simplify this, it uses the same API than Lustre to put keys on children.

fn my_component(props, children) {
  redraw.keyed(my_other_component(props, _), {
    use item <- list.map(children)
    #("my-key", item)
  })
}
pub fn memo(
  component: fn(props, List(Component)) -> Component,
) -> fn(props, List(Component)) -> Component

Memoizes a Redraw component with children.
Documentation

pub fn memo_(
  component: fn(props) -> Component,
) -> fn(props) -> Component

Memoizes a Redraw component without children.
Documentation

pub fn profiler(children: List(Component)) -> Component

Profile allows to measure code performance for a component tree.
Documentation

pub fn provider(
  context context: Context(a),
  value value: a,
  children children: List(Component),
) -> Component

Wrap your components into a context provider to specify the value of this context for all components inside.
Documentation

pub fn set_current(of ref: Ref(a), with value: a) -> Nil

Set the current value of a ref, overriding its existing content.

pub fn standalone(
  name name: String,
  render render: fn() -> Component,
) -> fn() -> Component

Create a Redraw standalone component, with a name and a render function. Keep in mind this component does not accept children nor props.

pub fn start_transition(scope scope: fn() -> Nil) -> Nil

Let you update the state without blocking the UI.
Documentation

pub fn strict_mode(children: List(Component)) -> Component

Strict Mode should be enabled during development.
Documentation

pub fn suspense(
  props: Suspense,
  children: List(Component),
) -> Component

Suspense allow to display a fallback content while waiting for children to finish loading.
Documentation

pub fn to_component(
  name name: String,
  component render: fn(props) -> Component,
) -> fn(props, children) -> Component

Convert a React component to a React-redraw component with children. Give it a name, and send directly the FFI. Don’t worry about the snake_case over camelCase, redraw take care of it for you.

Because children can accept anything, it’s up to you to define the type of the children. If you send a List, it will be automatically converted to a JavaScript array.

import redraw

pub type MyComponentProps {
  MyComponentProps(
    first_prop: Bool,
    second_prop: String,
  )
}

@external(javascript, "my_library", "MyComponent")
fn do_my_component(props: MyComponentProps) -> redraw.Component

pub fn my_component() -> fn(MyComponentProps, List(Component)) -> redraw.Component {
  redraw.to_component("MyComponent", do_my_component)
}
pub fn to_element(
  name name: String,
  component render: fn(props) -> Component,
) -> fn(props) -> Component

Convert a React Component to a Redraw Element. Give it a name, and send directly the FFI. Don’t worry about the snake_case over camelCase, redraw take care of it for you.

import redraw

pub type MyComponentProps {
  MyComponentProps(
    first_prop: Bool,
    second_prop: String,
  )
}

@external(javascript, "my_library", "MyComponent")
fn do_my_component(props: MyComponentProps) -> redraw.Component

pub fn my_component() -> fn(MyComponentProps) -> redraw.Component {
  redraw.to_element("MyComponent", do_my_component)
}
pub fn use_action_state(
  action: fn(state, payload) -> Nil,
  initial_state: state,
) -> #(state, fn(payload) -> nil, Bool)

Allow you to update state based on the result of a form action.
Documentation

pub fn use_async_transition() -> #(
  Bool,
  fn() -> promise.Promise(Nil),
)

Async variant of use_transition.
Documentation

pub fn use_callback(
  fun: function,
  dependencies: dependencies,
) -> function

Let you cache a function definition between re-renders. dependencies should be a tuple.
Documentation

pub fn use_context(context: Context(a)) -> a

Let you read and subscribe to context from your component.

Under-the-hood, use_context uses the new use function. This means you can call use_context conditionnally! \

Documentation

pub fn use_debug_value(value: a) -> Nil

Let you add a label to a custom Hook in React DevTools.
Documentation

pub fn use_debug_value_(
  value: a,
  formatter: fn(a) -> String,
) -> Nil

Let you add a label to a custom Hook in React DevTools, but allow to format it before.
Documentation

pub fn use_deferred_value(value: a) -> a

Let you defer updating a part of the UI.
Documentation

pub fn use_effect(value: fn() -> Nil, dependencies: a) -> Nil

Let you synchronize a component with an external system.
Documentation

pub fn use_effect_(
  value: fn() -> fn() -> Nil,
  dependencies: a,
) -> Nil

Let you synchronize a component with an external system. Allow to return a cleanup function.
Documentation

pub fn use_id() -> String

Generate unique IDs that can be passed to accessibility attributes.
Documentation

pub fn use_imperative_handle(
  ref: Ref(option.Option(a)),
  handler: fn() -> a,
  dependencies: b,
) -> Nil

Let you customize the handle exposed as a ref. Use use_imperative_handle when you want to customize the data stored in a ref.
Documentation

pub fn use_imperative_handle_(
  ref: Ref(a),
  handler: fn() -> a,
  dependencies: b,
) -> Nil

Let you customize the handle exposed as a ref. You should probably use use_imperative_handle by default with optional refs.
Documentation

pub fn use_insertion_effect(
  handler: fn() -> Nil,
  deps: deps,
) -> Nil

Allow inserting elements into the DOM before any layout Effects fire.

use_insertion_effect is for CSS-in-JS library authors. Unless you are working on a CSS-in-JS library and need a place to inject the styles, you probably want use_effect or use_layout_effect instead.

Documentation

pub fn use_insertion_effect_(
  handler: fn() -> fn() -> Nil,
  deps: deps,
) -> Nil

Allow inserting elements into the DOM before any layout Effects fire and allow to return a cleanup function.

use_insertion_effect is for CSS-in-JS library authors. Unless you are working on a CSS-in-JS library and need a place to inject the styles, you probably want use_effect or use_layout_effect instead.

Documentation

pub fn use_layout_effect(
  value: fn() -> Nil,
  dependencies: a,
) -> Nil

Version of useEffect that fires before the browser repaints the screen.
Documentation

pub fn use_lazy_state(
  initial_value: fn() -> a,
) -> #(a, fn(a) -> Nil)

Let you add a state variable to your component. Allow to create the initial value in a lazy way.
Documentation

pub fn use_lazy_state_(
  initial_value: fn() -> a,
) -> #(a, fn(fn(a) -> a) -> Nil)

Let you add a state variable to your component. Allow to create the initial value in a lazy way. Give an updater function instead of a state setter.
Documentation

pub fn use_memo(calculate_value: fn() -> a, dependencies: b) -> a

Let you cache the result of a calculation between re-renders.
Documentation

pub fn use_optimistic(state: state) -> #(state, fn(state) -> Nil)

Let you optimistically update the UI.
Documentation

pub fn use_optimistic_(
  state: state,
) -> #(state, fn(fn(state) -> state) -> Nil)

Let you optimistically update the UI.
Documentation

pub fn use_optimistic_action(
  state: state,
  update: fn(state, action) -> state,
) -> #(state, fn(action) -> Nil)

Let you optimistically update the UI.
Documentation

pub fn use_promise(promise: promise.Promise(state)) -> state

Wait for a Promise and returns its content. Uses use under-the-hood. When the Promise is loading, it fallbacks to the nearest Suspense boundary.
Documentation

pub fn use_reducer(
  reducer: fn(state, action) -> state,
  initial_state: state,
) -> #(state, fn(action) -> Nil)

Let you add a reducer to your component.
Documentation

pub fn use_reducer_(
  reducer: fn(state, action) -> state,
  initializer: initializer,
  init: fn(initializer) -> state,
) -> #(state, fn(action) -> Nil)

Let you add a reducer to your component. Allow to initialize the store in a custom way.
Documentation

pub fn use_ref() -> Ref(option.Option(a))

Let you reference a value that’s not needed for rendering. Most used ref you’ll want to create. They’re automatically created to None, and can be passed to ref prop or use_imperative_handle. You probably don’t want the ref value to be anything than Option(a), unless you have really strong reasons.
Documentation

pub fn use_ref_(initial_value: a) -> Ref(a)

Let you reference a value that’s not needed for rendering. Use use_ref if you’re trying to acquire a reference to a child or to a component. Use use_ref_ when you want to keep track of a data, like if you’re doing some side-effects, in conjuction with get_current and set_current.
Documentation

pub fn use_state(initial_value: a) -> #(a, fn(a) -> Nil)

Let you add a state variable to your component.
Documentation

pub fn use_state_(
  initial_value: a,
) -> #(a, fn(fn(a) -> a) -> Nil)

Let you add a state variable to your component. Give an updater function instead of a state setter.
Documentation

pub fn use_sync_external_store(
  subscribe: fn(fn() -> Nil) -> fn() -> Nil,
  get_snapshot: fn() -> snapshot,
) -> snapshot

Let you subscribe to an external store.
Documentation

pub fn use_transition() -> #(Bool, fn() -> Nil)

Let you update the state without blocking the UI.
Documentation

Search Document