hooks 系列一:简介

快来加入咱们吧!

"小和山的菜鸟们",为前端开发者提供技术相关资讯以及系列基础文章。为更好的用户体验,请您移至咱们官网小和山的菜鸟们 ( xhs-rookies.com/ ) 进行学习,及时获取最新文章。html

"Code tailor" ,若是您对咱们文章感兴趣、或是想提一些建议,微信关注 “小和山的菜鸟们” 公众号,与咱们取的联系,您也能够在微信上观看咱们的文章。每个建议或是赞同都是对咱们极大的鼓励!前端

React-Hooks 简介

react 为何要有一个 hooks?

1.有状态的类组件的复用太麻烦

react 的核心思想就是,将一个页面拆成一堆独立的,可复用的组件,而且用自上而下的单向数据流的形式将这些组件串联起来。但若是你在大型的工做项目中用 react,你会发现你的项目中实际上不少 react 组件冗长且难以复用。特别是那些 class 的组件,它们自己包含了 state,很难进行复用。node

官方推荐解决方案react

  • 渲染属性 - 使用一个值为函数的 prop 来传递须要动态渲染的 nodes 或组件.以下面的代码能够看到咱们的Provider组件包含了全部跟状态相关的代码,而 MyComponent 组件则能够是一个单纯的展现型组件,这样一来Provider就能够单独复用了
import MyComponent from 'components/myComponent'
class Provider extends React.Component {
  constructor(props) {
    super(props)
    this.state = { target: 'MyComponent' }
  }

  render() {
    return <div>{this.props.render(this.state)}</div>
  }
}

<Provider render={(data) => <MyComponent target={data.target} />} />
复制代码

这个模式叫 Render-Props .web

固然通常状况下,都会被写成下面这样的方式:ajax

<Provider>{(data) => <Cat target={data.target} />}</Provider>
复制代码
  • HOC 高阶组件 - 一个函数接受一个组件做为参数,通过一系列加工后,最后返回一个新的组件.看下面的代码示例,withUser 函数就是一个高阶组件,它返回了一个新的组件,这个组件具备了它提供的获取用户信息的功能。
const withUser = (WrappedComponent) => {
  const user = localStorage.getItem('user')
  return (props) => <WrappedComponent user={user} {...props} />
}

const UserPage = (props) => (
  <div class="user-page"> <p>I'm the user, {props.user}!</p> </div>
)

export default withUser(UserPage)
复制代码

以上这两种模式看上去都挺不错的,不少库也运用了这样的模式,就像咱们经常使用的 React-router 库。可是这两种模式,会增长代码的层级关系。为了表现的明显,能够安装打开 React Devtools 看看代码的组件嵌套,会发现嵌套次数太多太多。chrome

而若是咱们使用 hooks ,那就会简洁不少,没有多余的层级嵌套。把各类想要的功能写成一个一个可复用的自定义 hook,当你的组件想用什么功能时,直接在组件里调用这个 hook 便可。浏览器

2.生命周期函数里面逻辑比较复杂

咱们一般但愿一个函数只作一件事情,但咱们的生命周期钩子函数里一般同时作了不少事情。好比咱们须要在 componentDidMount 中发起请求获取数据,绑定一些事件监听等等。同时,有时候咱们还须要在 componentDidUpdate 作一遍一样的事情。缓存

当咱们的这个页面或者这个组件,变得复杂的时候,里面的内容就会变多,逻辑的清晰度就会降低。微信

3.class 中的 this 指向问题

父组件给子组件传递函数时, 必须绑定 this

  • react 中的组件四种绑定 this 方法的区别
class App extends React.Component<any, any> {
  handleClick2

  constructor(props) {
    super(props)
    this.state = {
      num: 1,
      title: ' react study',
    }
    this.handleClick2 = this.handleClick1.bind(this)
  }

  handleClick1() {
    this.setState({
      num: this.state.num + 1,
    })
  }

  handleClick3 = () => {
    this.setState({
      num: this.state.num + 1,
    })
  }

  render() {
    return (
      <div> <h2>Ann, {this.state.num}</h2> <button onClick={this.handleClick2}>btn1</button> <button onClick={this.handleClick1.bind(this)}>btn2</button> <button onClick={() => this.handleClick1()}>btn3</button> <button onClick={this.handleClick3}>btn4</button> </div>
    )
  }
}
复制代码
  • 构造函数中绑定 this,那么每次父组件刷新的时候,若是传递给子组件其余的 props 值不变,那么子组件就不会刷新
  • render() 函数里面绑定 this:由于 bind 函数会返回一个新的函数,因此每次父组件刷新时,都会从新生成一个函数,即便父组件传递给子组件其余的 props 值不变,子组件每次都会刷新;
  • ()=>{} 箭头函数:父组件刷新的时候,即便两个箭头函数的函数体是同样的,都会生成一个新的箭头函数,因此子组件每次都会刷新;
  • 使用类的静态属性:原理和第一种方法差很少,比第一种更简洁

综上所述,若是不注意的话,很容易写成第三种写法,致使性能上有所损耗

hooks 优势

  • 能优化类组件存在问题

  • 能在无需修改组件结构的状况下复用状态逻辑(**自定义 Hooks **)

  • 能将组件中相互关联的部分拆分红更小的函数(好比设置订阅或请求数据)

  • 反作用的关注点分离反作用指那些没有发生在数据向视图转换过程当中的逻辑,如 ajax 请求、访问原生dom 元素、本地持久化缓存、绑定/解绑事件、添加订阅、设置定时器、记录日志等。以往这些反作用都是写在类组件生命周期函数中的。而 useEffect 在所有渲染完毕后才会执行,useLayoutEffect 会在浏览器 layout 以后,painting 以前执行。

小结

如今,咱们对 hooks 已经有了一个大概的了解。

那么以后就开始咱们的基础 hooks 教程了。

hooks 系列中,咱们主要介绍四个项目中经常使用的钩子:useStateuseEffectuseRefsuseCallback.

若是大家想要了解一些其余钩子函数(useContextuseReduceruseMemouseImperativeMethodsuseMutationEffectuseLayoutEffect),能够去官网查看

下节预告

在下节中,咱们将为你们介绍 useState ,敬请期待!

相关文章
相关标签/搜索