Re: 新手让网页 act 起来: Day29 - React hooks 之 Custom hook

前言

Custom hook 让我们可以将 component 的逻辑提取出来到一个 function 中,让我们可以重复的使用它,甚至运用在不同的 component 中。而当我们要写一个 Custom hook 时,要注意这个 function 的命名一定要是 use 开头,因为这样子 React 才会知道你在这个 function 中使用了 hook ,并检查是否有违反 Hook 规则的行为。接下来就让我们来实际练习看看,如何写出一个 Custom hook 吧!!

useLocalStorageState

function App() {
  const [name, setName] = React.useState(() => {
    return window.localStorage.getItem('name') || ''
  })

  function onChangeHandler(e) {
    setName(e.target.value)
  }

  React.useEffect(() => {
    window.localStorage.setItem('name', name)
  }, [name])

  return (
    <div>
      <form>
        <label htmlFor="name">Name: </label>
        <input id="name" type="text" value={name} onChange={onChangeHandler} />
      </form>
    </div>
  )
}

ReactDOM.render(<App />, document.getElementById('root'));

上面的范例中,我们有个 input,当值改变的时候我们会存入 localStorage ,而浏览器重新整理时,会先去看 localStorage 是否有值,并设为初始值。范例的程序码看起来没有太大的问题,但假设,我们有其他的 state,也需要存入 localStorage,或许就可以考虑把这个行为做抽象化。接下来让我们来试着完成 useLocalStorageState 吧!

  1. 定义 useLocalStorageState
function useLocalStorageState(){
    
}
  1. 期望当使用 useLocalStorageState 一样会回传 state 与 setState
function useLocalStorageState(initialValue = ''){
  const [state, setState] = React.useState(initialValue)
  
  return [state, setState]
}

const [name, setName] = useLocalStorageState(initialValue)
  1. 将 useEffect 与 lazyInitalize 放进 useLocalStorageState
function useLocalStorageState(initialValue = ''){
  const [state, setState] = React.useState(()=>{
     return window.localStorage.getItem('name') || initialValue
  })
  
   React.useEffect(() => {
    window.localStorage.setItem('name', name)
  }, [name])
  
  return [state, setState]
}
  1. 将 key 设为引数,并更改 dependency
function useLocalStorageState(key, initialValue = ''){
  const [state, setState] = React.useState(()=>{
     return window.localStorage.getItem(key) || initialValue
  })
  
   React.useEffect(() => {
    window.localStorage.setItem(key, state)
  }, [state])
  
  return [state, setState]
 }
 
  1. 考量传进来的 initialValue 是 callback,以及将存入的资料转为字串,取的时候转回原本格式
function useLocalStorageState(key, initialValue = '') {
  const [state, setState] = React.useState(() => {
    const storageValue = window.localStorage.getItem(key)
    if (storageValue) return JSON.parse(storageValue)

    return typeof initialValue === 'function' ? initialValue() : initialValue
  })

  React.useEffect(() => {
    window.localStorage.setItem(key, JSON.stringify(state))
  }, [state])

  return [state, setState]
}

这样子我们就完成一个基本的 useLocalStorageState Custom hook 了,接下来我们就可以很容易的增加想要存进 localStoragae 的 state 了!

function App() {
  const [name, setName] = useLocalStorageState('name', '')
  const [count, setCount] = useLocalStorageState('count', 0)

  function onChangeHandler(e) {
    setName(e.target.value)
  }

  return (
    <div>
      <form>
        <label htmlFor="name">Name: </label>
        <input id="name" type="text" value={name} onChange={onChangeHandler} />
      </form>
      <button onClick={() => setCount(count + 1)}>{count}</button>
    </div>
  )
}

ReactDOM.render(<App />, document.getElementById('root'));

以上就是今天的分享,如果有任何问题都欢迎在下方留言!

该文章同步发布於:我的部落格


<<:  [Day29] 资安自学之路 小回顾

>>:  D29 - 彭彭的课程# Python Pandas 资料分析 - 基础教学

Day28 vue.js搜寻栏 分页(pagination)功能

延续昨日 今天我们且战且走 首先先把最简单的排序专案方法搞定 先创一个sortby function...

Day 10 | Unity AR 环境建置(Android)

在开始开发游戏之前,要先把环境建置好,不然在之後输出的时候,档案有可能会无法输出或无法执行。本篇会针...

Day 30 - 结语 : 从"预见到坚持"

终於来到今年铁人赛的最後一篇了~虽然都有预先写稿的习惯与准备, 但这次还真的是忙到最後一天才能抽空...

[DAY 30] 总结及回顾

机器人与我们同在 大家好,虽然令人不舍,但这天还是来临了 。30天的时间倏忽即逝,是时候跟大家道别了...

Day 17 JavaScript bind vs call vs apply

共同点: 原本的 this 是指向全域物件 window ,使用 bind、call、apply ...