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" }
第一家钩厂
它将是一个自定义钩子包装,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>
</>
)
}
具有自定义逻辑的 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>
</>
)
}
跨钩子共享状态以创建上下文,无需 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 />
</>
)
}
现在,这个钩子提供了一个共享状态,而不必用上下文提供程序包装应用程序。
无需包装树的大部分内容,从而提供了一种优化重新渲染的替代方法,而无需诉诸更高级的 API。
谁在使用这种模式?
Material-UI的makeStyles
功能允许为特定组件创建样式。
use-local-storage-state——启发我写这篇博文的主要例子。
综上所述
React Hooks 是生态系统中组合功能的绝佳方式。在其基础上添加工厂模式,可以带来更多有趣的解决问题方式,而不仅仅是将 Hooks 拼接在一起。
鏂囩珷鏉ユ簮锛�https://dev.to/pietmichal/react-hooks-factories-48bi