hooks

简述

Hooks?

hooks 是 React v16.7.0-alpha 加入的新特性,可以在 class 外使用 state 以及其他 React 新特性。

优点

  • 相比类来说,相似的逻辑不再分隔开,代码更简洁

useState

  1. 和类的对比

一个计数小例子(来自官网~)

类方法实现:
import React from 'react';
class Example extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
  }

  render() {
    return (
      <>
        <div>You clicked {this.state.count} times</div>
        <button onClick={() => this.setState({ count: this.state.count + 1 })}>add</button>
        <button onClick={() => this.setState({ count: this.state.count - 1 })}>reduce</button>
      </>
    );
  }
}
export default Example
useState 实现:
import React,{ useState } from 'react';
import  styles from './main.module.less';

function Example() {
  const [count,setCount] = useState(1);
  return (
    <>
    <div className={styles.container}>you clicked {count} times</div>
    <button onClick={()=>setCount(count+1)}>add</button>
    <button onClick={()=>setCount(count-1)}>reduce</button>
  </>
  );
}

export default Example;
  1. useState
const [count,setCount] = useState(1);
// useState 返回的是一对值,如下:
var countStateVariable = useState(1); 
var count = countStateVariable[0]; // 第一个元素
var setCount = countStateVariable[1]; // 第二个元素

// 使用的是js的"数组破坏",官方解释使用[0]和[1]会有很大的迷惑性~

多个 state 怎么写?我们可以使用多个 useState.

function Example() {
  const [count,setCount] = useState(1);
  const [age,setAge] = useState(10);
  const [fruit,setFriute] = useState('apple');
  const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]);
  
  return (
    <>
    <div className={styles.container}>you clicked {count} times</div>
    <button onClick={()=>setCount(count+1)}>add</button>
    <button onClick={()=>setCount(count-1)}>reduce</button>
  </>
  );
}

那么React是怎么记住"哪个状态对应哪个 useState"? 答案就是依赖调用钩子函数的顺序。所以存在了几条规范

useEffect

useEffect 允许你在功能组件里面执行副作用

  • 和类的对比
类方法实现:
class Example extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0,
      data:{},
    };
  }

  componentDidMount(){
    fetch('/api/xiaoyi/goodsList').then(res=>res.json()).then(data=>{
      console.log(data,'data')
      setState({data})
    })
    window.addEventListener('resize', this.getHeight);
  }
  
  componentDidUpdate(preProps){
    if(preProp.id!==this.props.id){
      fetch('/api/xiaoyi/goodsList').then(res=>res.json()).then(data=>{
        console.log(data,'data')
      })
    }
  }

   componentWillUnmount() {
    window.remoteEventListener('resize', this.getHeight);
  }
  
  render() {
    return (
      <>
        <div>You clicked {this.state.count} times</div>
        <button onClick={() => this.setState({ count: this.state.count + 1 })}>add</button>
        <button onClick={() => this.setState({ count: this.state.count - 1 })}>reduce</button>
      </>
    );
  }
}
export default Example
useEffect 实现:
import React,{ useState, useEffect } from 'react';
import  styles from './main.module.less';

function Example(props) {
  const [count,setCount] = useState(1);
  useEffect(()=>{
    fetch('/api/xiaoyi/goodsList').then(res=>res.json()).then(data=>{
      console.log(data,'data')
    })
    window.addEventListener('resize', ()=>{console.log(111)});
    
    return () => {
      window.removeEventListener('resize', ()=>{console.log(111)});
        }
  },[props.id])
  return (
    <>
    <div className={styles.container}>you clicked {count} times</div>
    <button onClick={()=>setCount(count+1)}>add</button>
    <button onClick={()=>setCount(count-1)}>reduce</button>

  </>
  );
}

export default Example;

Hooks允许我们根据代码所做的而不是生命周期方法名来分割代码。

useEffect 的参数是一个函数,组件每次渲染之后,都会调用这个函数参数,这样就达到了 componentDidMount 和 componentDidUpdate 一样的效果。

useEffect 第一个参数返回的一个函数相当于清除该副作用,会在每次渲染执行。

为什么不在组件销毁的时候执行?<br /> 因为如果要销毁的内容中间发生改变,在销毁的时候,销毁的就是之前的内容,不是当前要销毁的了,就会产生bug。

useEffect 的第二个参数,代表重新渲染如果这个值未发生变化,就跳过渲染。

如果要运行一个 effect 并只清理一次(在装载和卸载时),可以将空数组([])作为第二个参数传递。这告诉react,您的效果不依赖于来自props或state的任何值,因此它不需要重新运行。这并不是一个特殊的情况——它直接来自于输入数组的工作方式。

rules

使用 hooks 的规则
  • 不要在循环,条件或嵌套函数内使用钩子函数。相反,要在函数顶层使用钩子。
  • 不要在常规的js函数里面使用钩子函数
  • 可以自定义的钩子函数里面使用
    <a name="WluJO"></a>
react 提供了esLint插件 [eslint-plugin-react-hooks](https://www.npmjs.com/package/eslint-plugin-react-hooks) 来帮助我们执行这些规则
  • npm install eslint-plugin-react-hooks@next
规则由来

由上面可知,单个组件使用多个 State 或者 Effect 钩子函数时候,React 依赖调用钩子函数的顺序记住相对应的状态的。所以当使用条件判断时候:

// 打破了第一条规则
  if (name !== '') {
    useEffect(function persistForm() {
      localStorage.setItem('formData', name);
    });
  }

当第一次render,name!==''为true的时候,这个钩子函数会执行;当下一次为false的时候,渲染就会跳过这个钩子函数。此时钩子的调用顺序发生了改变。(加入这个钩子函数之前和之后都存在其他钩子函数)

useState('loving')          
// useEffect(persistForm)  // 这个 hook 将会被跳过
useState('lili')        // 现在读取是2,但是之前是3,读取这个状态变量就会出错。

react不知道第二次useState hook调用返回什么。react预期此组件中的第二个hook调用与PersisteForm效果相对应,就像在上一次呈现期间一样,但它不再如此。从那时起,我们跳过的钩子调用之后的每一个钩子调用也会一个接一个地移动,从而导致错误。

useEffect(function persistForm() {
    // 👍不会打破第一条规则
    if (name !== '') {
      localStorage.setItem('formData', name);
    }
  });

参考文档:https://www.reactjscn.com/docs/hooks-state.html

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,530评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,403评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,120评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,770评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,758评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,649评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,021评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,675评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,931评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,751评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,410评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,004评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,969评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,042评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,493评论 2 343

推荐阅读更多精彩内容