redraw

Types

Default Node in redraw. Use component-family functions to create components. Forwarded ref can be constructed using forward_ref-family functions, while external components can be used with to_component-family functions.

pub type Component

Pass data without props drilling.

Documentation

pub type Context(a)

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

  • Suspense(fallback: Component)

Functions

pub fn act(act_fn: fn() -> Promise(Nil)) -> Promise(Nil)

Test helper to apply pending React updates before making assertions.

Documentation

pub fn component(
  name name: String,
  render render: fn(a, List(Component)) -> Component,
) -> fn(a, List(Component)) -> Component

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

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

Create a Redraw component, with a name, and a render function. This component does not accept children.

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

Create a Redraw component, with a name and a render function. This component does not accept children nor props.

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(
  default_value default_value: Option(a),
) -> Context(a)

Deprecated: Use redraw/create_context_ instead. redraw/create_context will be removed in 2.0.0. Unusable right now, due to how React handles Context.

Let you create a context that components can provide or read.

Documentation

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 forward_ref(
  name name: String,
  render render: fn(a, Ref(b), List(Component)) -> Component,
) -> fn(a, Ref(b), List(Component)) -> Component

Create a Redraw component with children with forwarded ref. Take a look at

Documentation

pub fn forward_ref_(
  name name: String,
  render render: fn(a, Ref(b)) -> Component,
) -> fn(a, Ref(b)) -> Component

Create a Redraw component without children with forwarded ref. Take a look at

Documentation

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(a, List(Component)) -> Component,
) -> fn(a, List(Component)) -> Component

Memoizes a Redraw component with children.

Documentation

pub fn memo_(component: fn(a) -> Component) -> fn(a) -> 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 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(a) -> Component,
) -> fn(b, List(Component)) -> 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.

import redraw

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

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

pub fn my_component() -> fn(MyComponentProps) -> redraw.Component {
  redraw.to_component("MyComponent", do_my_component)
}
pub fn to_component_(
  name name: String,
  component render: fn(a) -> Component,
) -> fn(b) -> Component

Convert a React Component to a redraw Component without 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.

import redraw

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

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

pub fn my_component() -> fn(MyComponentProps) -> redraw.Component {
  redraw.to_component_("MyComponent", do_my_component)
}
pub fn use_callback(fun: a, dependencies: b) -> a

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.

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(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. It’s mostly used in conjuction with forward_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. Use use_imperative_handle by default, unless you really know what you’re doing.

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_reducer(
  reducer: fn(a, b) -> a,
  initial_state: a,
) -> #(a, fn(b) -> Nil)

Let you add a reducer to your component.

Documentation

pub fn use_reducer_(
  reducer: fn(a, b) -> a,
  initializer: c,
  init: fn(c) -> a,
) -> #(a, fn(b) -> 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(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 attribute.ref 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_transition() -> #(Bool, fn() -> Nil)

Let you update the state without blocking the UI.

Documentation

Search Document