React Hooks 工厂

2025-06-10

React Hooks 工厂

带有 React Hooks 的工厂模式很少被提及,但是,它经常在流行的库中使用,以将组合推向极限。

它还可以用于简化(在某些情况下优化)整个 React 应用程序的状态共享。

工厂模式速成课程

工厂模式用于带来在运行时创建对象的能力。

它通常看起来像这样。请记住,这些只是用来描绘的简单示例。

interface User {
  name: string
}

class Factory {
  public static getUser(name: string): User {
    return { name }
  }
}

const user = Factory.getUser("Bob") // { name: "Bob" }

// Alternatively, without classes

function getUser(name: string): User {
  return { name }
}

const user = getUser("Bob") // { name: "Bob" }
Enter fullscreen mode Exit fullscreen mode

第一家钩厂

它将是一个自定义钩子包装,useState但它将设置在创建时提供的默认值。

// Factory function that returns a new function that uses Hooks API.
function createHook(initialValue: string) {
  return function useHook() {
    return React.useState(initialValue)
  }
}

// Create the hook.
const useHook = createHook("some initial value")

// Use the hook in the component.
// The component will output: "State is: some initial value"
function Component() {
  const [state] = useHook()
  return (
    <>
      State is: <b>{state}</b>
    </>
  )
}
Enter fullscreen mode Exit fullscreen mode

具有自定义逻辑的 Hook Factory

工厂模式解锁了更高层次的组合能力。
例如,工厂可以生成一个钩子,并在创建时赋予其自定义逻辑。

// Factory function that returns a new function that uses Hooks API.
function createMappedState(mapper: (value: string) => string) {
  return function useHook(initialValue: string) {
    const [state, setState] = React.useState(mapper(initialValue))

    // Define a custom setter applying custom logic.
    const setter = React.useCallback(
      (value: string) => {
        setState(mapper(value))
      },
      [setState]
    )

    // return a tuple to make API similar to React.useState
    return [state, setter]
  }
}

// You can create as many custom hooks you need
const useUppercasedString = createMappedState(value => value.toUpperCase())
const useLowercasedString = createMappedState(value => value.toLowerCase())

// Use the hook in the component.
// The component will output:
// `
// String is: SOME VALUE
// String is: some value
// `
function Component() {
  const [string1, setString1] = useUppercasedString("Some Value")
  const [string2, setString2] = useLowercasedString("Some Value")
  return (
    <>
      String1 is: <b>{string1}</b>
      <br />
      String2 is: <b>{string2}</b>
    </>
  )
}
Enter fullscreen mode Exit fullscreen mode

跨钩子共享状态以创建上下文,无需 Context API

当您意识到新功能可以访问工厂的范围时,工厂就会变得有趣。

function createSharedStateHook(initialValue: string) {
  let sharedValue = initialValue

  // An array in a shared scope.
  // Produced hook will always refer to it.
  const stateSetters: ((v: string) => void)[] = []

  // This function will update all components
  // that use the hook created by the factory.
  function setAllStates(value: string) {
    sharedValue = value
    stateSetters.forEach(set => {
      set(value)
    })
  }

  return function useSharedState(): [string, (v: string) => void] {
    const [state, setState] = React.useState(sharedValue)

    React.useEffect(() => {
      // On mount, add the setter to shared array.
      const length = stateSetters.push(setState)
      const index = length - 1
      return () => {
        // On unmount, remove the setter.
        stateSetters.splice(index, 1)
      }
    }, [setState])

    // The trick is to have the hook to return the same instance of `setAllStates`
    // at all times so the update will propagate through all components using the produced hook.
    return [state, setAllStates]
  }
}

const useSharedState = createSharedStateHook("initial")
const useAnotherSharedState = createSharedStateHook("another initial")

// `useSharedState` and `useAnotherSharedState` do not share the same state
// because returned hooks have access to different scopes.

function Component() {
  const [sharedState] = useSharedState()
  return (
    <>
      Shared state is: <b>{sharedState}</b>
    </>
  )
}

function AnotherComponent() {
  const [sharedState] = useAnotherSharedState()
  return (
    <>
      Another shared state is: <b>{sharedState}</b>
    </>
  )
}

function Modifier() {
  const [sharedState, setSharedState] = useSharedState()
  return (
    <input
      type="text"
      value={sharedState}
      onChange={e => setSharedState(e.target.value)}
    />
  )
}

function App() {
  return (
    <>
      <Component />
      <br />
      <AnotherComponent />
      <br />
      <Component />
      <br />
      <Modifier />
    </>
  )
}
Enter fullscreen mode Exit fullscreen mode

现在,这个钩子提供了一个共享状态,而不必用上下文提供程序包装应用程序。

无需包装树的大部分内容,从而提供了一种优化重新渲染的替代方法,而无需诉诸更高级的 API。

谁在使用这种模式?

Material-UImakeStyles功能允许为特定组件创建样式。

use-local-storage-state——启发我写这篇博文的主要例子。

综上所述

React Hooks 是生态系统中组合功能的绝佳方式。在其基础上添加工厂模式,可以带来更多有趣的解决问题方式,而不仅仅是将 Hooks 拼接在一起。

鏂囩珷鏉ユ簮锛�https://dev.to/pietmichal/react-hooks-factories-48bi
PREV
介绍:Pika CDN + Deno
NEXT
每种排序算法的适用范围