Date: YYYY-MM-DD
Status: Accepted | Deprecated | Replaced by [000][template]
Warning
This decision is deprecated. >
| import { useLocation, useNavigation, useSearchParams } from "@remix-run/react"; | |
| import { useCallback, useMemo } from "react"; | |
| export function useOptimisticSearchParams() { | |
| const location = useLocation(); | |
| const [searchParams, setSearchParams] = useSearchParams(); | |
| const navigation = useNavigation(); | |
| const nextSearchParams = useMemo(() => { | |
| if (navigation.location?.pathname === location.pathname) { |
| import { useSearchParams } from "@remix-run/react"; | |
| import isEqual from "lodash.isequal"; | |
| import { useCallback, useMemo } from "react"; | |
| import type { NavigateOptions } from "react-router"; | |
| export function useParsedSearchParams< | |
| TOutput extends object, | |
| TInput extends object, | |
| >(delegate: URLSearchParamsDelegate<TOutput, TInput>) { | |
| const [searchParams, setSearchParams] = useSearchParams(); |
| import { useMemo } from "react"; | |
| export function useComposedRef<TElement>(handlers: RefHandler<TElement>[]) { | |
| // We actually want the handlers to be the dependency list. | |
| // eslint-disable-next-line react-hooks/exhaustive-deps | |
| return useMemo(() => composeRefs(handlers), handlers); | |
| } | |
| function composeRefs<TElement>( | |
| handlers: RefHandler<TElement>[], |
| // Shared URL query that can be imported from anywhere. | |
| const PaginationUrlQuerySchema = z.object({ | |
| // Use .catch() in order to return a default value when validation fails. | |
| // See https://zod.dev/?id=catch | |
| page: z.coerce.number().min(0).catch(0), | |
| }); | |
| // Page specific URL query combined with shared ones. | |
| const MyPageUrlQuerySchema = PaginationUrlQuerySchema.extend({ | |
| enum: z.enum(["foo", "bar"]).catch("foo"), |
Extracted from https://stackoverflow.com/a/50396312
As you are likely aware, TypeScript adds a static type system to JavaScript, and that type system gets erased when the code is transpiled. The syntax of TypeScript is such that some expressions and statements refer to values that exist at runtime, while other expressions and statements refer to types that exist only at design/compile time. Values have types, but they are not types themselves. Importantly, there are some places in the code where the compiler will expect a value and interpret the expression it finds as a value if possible, and other places where the compiler will expect a type and interpret the expression it finds as a type if possible.
The compiler does not care or get confused if it is possible for an expression to be interpreted as both a value and a type.
| import throttle from 'lodash.throttle' | |
| const DEFAULT_HISTORY_CAPACITY = 50 | |
| const DEFAULT_PUSH_THROTTLE_TIMEOUT = 500 | |
| /** | |
| * The object defining the internal state of a History returned by | |
| * `History.getState`. | |
| * | |
| * @template T |
| import invariant from 'invariant' | |
| import warning from 'warning' | |
| function identity(state) { | |
| return state | |
| } | |
| function parse(serializedJSON) { | |
| if (serializedJSON) { | |
| try { |
| /** Geohashes are in base32. */ | |
| const MAX_CHILDREN_COUNT = 32 | |
| /** | |
| * Compress an array of Geohashes using Hash Tree compression. | |
| * | |
| * @param {string[]} geohashes Array of Geohashes. | |
| * @param {number} [minChildrenCount=32] The minimum number of children to concider a node full. | |
| * @returns {string[]} A compressed version of the Geohashes. | |
| */ |