[React] useReducer with lazy initializtion

const [state, dispatch] = useReducer(reducer, initialArg, init);

The third arguement 'init' is a lazy initialization which is a function.

It is useful when you want to reset the state or dynamiclly generate the state.

复制代码
function init(initialCount) {
  return {count: initialCount};
}

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return {count: state.count + 1};
    case 'decrement':
      return {count: state.count - 1};
    case 'reset':
      return init(action.payload);
    default:
      throw new Error();
  }
}

function Counter({initialCount}) {
  const [state, dispatch] = useReducer(reducer, initialCount, init);
  return (
    <>
      Count: {state.count}
      <button
        onClick={() => dispatch({type: 'reset', payload: initialCount})}>

        Reset
      </button>
      <button onClick={() => dispatch({type: 'decrement'})}>-</button>
      <button onClick={() => dispatch({type: 'increment'})}>+</button>
    </>
  );
}
复制代码

 

 

Or dyanmically generate the init val:

复制代码
const preferDarkQuery = '(prefers-color-scheme: dark)'
function darkModeReducer(state, action) {
  switch (action.type) {
    case 'MEDIA_CHANGE': {
      return {...state, mode: action.mode}
    }
    case 'SET_MODE': {
      // make sure to spread that state just in case!
      return {...state, mode: action.mode}
    }
    default: {
      // helps us avoid typos!
      throw new Error(`Unhandled action type: ${action.type}`)
    }
  }
}
// use the init function to lazily initialize state so we don't read into
// localstorage or call matchMedia every render
function init() {
  return {
    mode:
      window.localStorage.getItem('colorMode') ||
      (window.matchMedia(preferDarkQuery).matches ? 'dark' : 'light'),
  }
}
function useDarkMode() {
  const [state, dispatch] = React.useReducer(
    darkModeReducer,
    {mode: 'light'},
    init,
  )
  const {mode} = state
  React.useEffect(() => {
    const mediaQuery = window.matchMedia(preferDarkQuery)
    const handleChange = () =>
      dispatch({
        type: 'MEDIA_CHANGE',
        mode: mediaQuery.matches ? 'dark' : 'light',
      })
    mediaQuery.addListener(handleChange)
    return () => mediaQuery.removeListener(handleChange)
  }, [])
  React.useEffect(() => {
    window.localStorage.setItem('colorMode', mode)
  }, [mode])
  // We like the API the way it is, so instead of returning the state object
  // and the dispatch function, we'll return the `mode` property and we'll
  // create a setMode helper (which we have to memoize in case someone wants
  // to use it in a dependency list):
  const setMode = React.useCallback(
    newMode => dispatch({type: 'SET_MODE', mode: newMode}),
    [],
  )
  return [mode, setMode]
}
复制代码

 'init' function will override the second arguement.

 

More

posted @   Zhentiw  阅读(214)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
历史上的今天:
2019-03-10 [Algorithm] Print All Subsets of a Set
2019-03-10 [Functional Programming] mapReduce over Async operations and fanout results in Pair(rejected, resolved) (fanout, flip, mapReduce)
2019-03-10 [Functional Programming] mapReduce over Async operations with first success prediction (fromNode, alt, mapReduce, maybeToAsync)
2017-03-10 [Angular] Export directive functionalities by using 'exportAs'
2017-03-10 [Postgres] Group and Aggregate Data in Postgres
2017-03-10 [Ramda] Create a Query String from an Object using Ramda's toPairs function
2017-03-10 [Ramda] Filter an Array Based on Multiple Predicates with Ramda's allPass Function
点击右上角即可分享
微信分享提示