Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

React hooks 相关文档 #53

Open
wangpin34 opened this issue Mar 9, 2020 · 0 comments
Open

React hooks 相关文档 #53

wangpin34 opened this issue Mar 9, 2020 · 0 comments
Labels

Comments

@wangpin34
Copy link
Owner

wangpin34 commented Mar 9, 2020

从去年下半年以来开始实践 React Hooks,到现在一年多时间,谈谈感想。

相比 Class 组件

React 官方包括社区里很多大神解释过为什么 Hooks 是更好的选择,从提高编译效率,运行效率,开发体验多个方面都总结出很多很棒的例子。作为普通开发者,我更加看中的是最后一点,因为这与自己的日常工作息息相关,这倒不是说其他两个就不重要了,只是对于个人的影响没有那么深刻。
那么,Hooks 带来了什么好处呢?
首先,使用 Hooks 可以更加方便的描述数据之间的依赖关系,最典型的如 useMemo 的用法,如下,通过 a,b 推导出 c。

const { a, b } = props
const c = useMemo(() => a + b, [a, b])

c 是 jsx 里直接使用的变量,当然,这个例子不太具有说服力。但是这里的数据联动关系更加清晰了。当 a,b 变化时,重新计算 c 的值。

其次,side effect 更加直观,以往在 class 组件中,需要在特定的 life cycle 如 componentDidMount 这样的方法里管理 side-effect,使用 Hooks 可以直接编写。

useEffect(() => {
  document.body.addEventListener('resize', onResize)
}, [])

而且,可以很方便的在 effect 退出时就地清理现场。

useEffect(() => {
  document.body.addEventListener('resize', onResize)
  return () => {
    document.body.removeEventListener('resize', onResize)
  }
}, [])

而不用像 class 组件中,先将 onResize 保存为实例变量,然后在 compoentWillUnmount 中清理。

最后,也是使用 Hooks 一段时间感受到,除了 useEffect,其他 Hooks 都是没有副作用的纯数据。那将某些可以重用的 Hooks 单独拿出来定义,然后组合起来使用,也是很自然的事情。这就是 custom Hooks。

相比 HOC

在 Hooks 之前,很多重用逻辑的场合,如导入额外的 props,需要使用 HOC。如常见的,withRouter(react-router-dom),withStyles(material-design)。如果需要导入的东西比较多,就会写成这样:withStyles(withRouter(withX(withY(withZ(Component))))),少一个括号就能debug半天。

Hooks 发布之后,这些 lib 也实现了 Hooks 接口,代码看起来会像这样:

function Component() {
  const history = useHistory()
  const classes = useStyles()
  // others
}

可阅读性提高很多。

此外,自己定制 Hooks 也极其简单,比如,我自己做了一个 file picker。

import { useMemo, useEffect } from 'react'
import { useObservable } from 'rxjs-hooks'
import { BehaviorSubject } from 'rxjs'

function useFilepicker() {
  const subject$ = useMemo(() => new BehaviorSubject<string>(''), [])
  const v$ = useMemo(() => new BehaviorSubject<{ name?: string; content?: string } | null>(null), [])
  const v = useObservable(() => v$)
  useEffect(() => {
    const input = document.createElement('input')
    input.type = 'file'
    input.name = 'my-file'
    input.style.display = 'none'
    document.body.appendChild(input)

    const onChange: EventListener = (event: Event): any => {
      const files = (event.target as HTMLInputElement).files
      if (files && files.length) {
        const file = files[0]
        const fileReader = new FileReader()
        fileReader.readAsText(file)
        fileReader.onload = (e: ProgressEvent<FileReader>): any => {
          console.log('File read operation successfully complete')
          const result = e.target ? (e.target.result as string) : ''
          v$.next({
            name: file.name,
            content: result,
          })
        }
      }
      return
    }

    input.addEventListener('change', onChange)

    const subscrition = subject$.subscribe((v) => {
      console.log(`Received message from handlers: ${v}`)
      if (v === 'open') {
        input.click()
      }
    })

    return () => {
      input.removeEventListener('change', onChange)
      document.body.removeChild(input)
      subscrition.unsubscribe()
    }
  }, [subject$, v$])

  return useMemo(
    () => ({
      handlers: {
        open: () => subject$.next('open'),
      },
      value: v,
    }),
    [subject$, v]
  )
}

export default useFilepicker

总结

诞生于 2018 年的 Hooks 已经面世两年时间了,从我个人的体验来说,Hooks 对开发体验的提升是一场革命。开发人员可以用更清晰地数据逻辑来编写组件,更简单地方式来封装数据以及数据相关的逻辑。

我想,我是真的离不开 Hooks 了(笑)。

下面是收藏的一些关于 Hooks 的文章。

文章

@wangpin34 wangpin34 added 文章 and removed 周记 labels Jul 7, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant