Skip to content

Add JSDoc comments to exposed functionality so users get documentation in their editor #7

Description

@ahrjarrett

Example:

// `src/state.ts`
import * as E from 'fp-ts/Either'
import * as Eq from 'fp-ts/Eq'
import * as O from 'fp-ts/Option'
import { Dispatch, SetStateAction, useReducer } from 'react'

const isSetStateFn = <A>(s: SetStateAction<A>): s is (a: A) => A => typeof s === 'function'

/**
 * `useStable` is roughly analogous to React's `setState`, the difference being 
 * that `useStable` exposes a way for users to define how React should interpret
 * two values when determining whether to trigger a re-render.
 *
 * The reason this is useful is because internally React uses `Object.is` to compare
 * states. While this is a reasonable default given their goal of simplifying their API,
 * it can sometimes lead to surprising behavior, and leads to awkward workarounds 
 * that can lead to code that is difficult to read or debug.
 * 
 * `useStable` makes a different tradeoff, accepting the cost of being explicit upfront
 * for more predictable updates/re-rendering at the call site. Users define what it means
 * for 2 stateful values to be equivalent (in the form of a binary function), and updates 
 * don't occur until the function evaluates to false. 
 * 
 * @example
 * ```typescript
 *  import * as Eq from "fp-ts/Eq"
 *  import * as O from "fp-ts/Option"
 *  import * as N from "fp-ts/number"
 *  import * as S from "fp-ts/string"
 *  import { useStable } from "fp-ts-react-stable-hooks"
 * 
 *  const initialValue = { id: 1, name: "oof" }
 *  const eq = Eq.struct({ id: N.Eq, name: S.Eq })
 * 
 *  // Now, `data` will only trigger a re-render if its _value_ has changed:
 *  const [data, setData] = useStable(initialValue, eq)
 * ```
 *
 * @since 1.0.0 (or whatever)
 */
export const useStable = <A>(initState: A, eq: Eq.Eq<A>): [A, Dispatch<SetStateAction<A>>] =>
  useReducer(
    (s1: A, s2: SetStateAction<A>) => {
      const _s2 = isSetStateFn(s2) ? s2(s1) : s2
      return eq.equals(s1, _s2) ? s1 : _s2
    },
    initState
  )

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions