react随笔之hooks(一)

Hooks使用条件

目前用create-react-app脚手架创建的项目,react和react-dom版本为^16.7.0,该版本还未支持hooks的使用,未升级使用会报错误:TypeError: Object(…) is not a function。

升级react的版本很简单,在该项目目录下执行如下语句即可。

yarn add react@next react-dom@next

完成后可查看package.json文件是否升级成功,该文章代码是基于react react-dom ^16.8.0-alpha.1版本运行的。

Hooks是写在React function里面的,与之前的class不同,就像官网的例子里一样。我们可以这样

const Example = (props) => {
  // You can use Hooks here!
  return <div />;
}

或者这样

function Example(props) {
  // You can use Hooks here!
  return <div />;
}

又或者直接

export default (props) => {
  // You can use Hooks here!
  return <div />;
}

总之

  • 只在 React Functions 调用 Hooks
  • 只在顶层调用Hook,不能在循环,条件或嵌套函数中调用Hook

useState

首先需要import一下useState

import React, { useState } from "react";

然后我们就可以在function里面使用了,以count为例,方法如下

const [count, setCount] = useState(0);

count是state,0是count的初始值,setCount是设置count的一个函数(函数名不一定要是setXxx,也可以如sCount等,但不建议这么做),setCount()等效于👇

setCount = (count) => {
    this.setState({
      count
    })
  }

useState只能在顶层调用,不能在循环,条件或嵌套函数中调用,因为useSate是基于数组的实现的,而他们的下标是根据useState出现顺序决定的,假设判断语句中存在useState,当判断不成立时(即不执行判断包裹的代码时),useState会因为下标错乱而出错。想了解更多可看React hooks: not magic, just arrays (需科学上网)或官网的Rules of Hooks

具体使用如下:

import React, { useState } from 'react';
function Cunter() {
  const [count, setCount] = useState(0);

  return (
    <div className="count-box">
      <h1 className="title">点了{count}次</h1>
      <button onClick={() => {setCount(count + 1);}}>Click Me!</button>
    </div>
  );
}
export default Cunter;

useEffect

useEffect结合了componentWillMount、componentDidMount和componentWillUnmount的特性。useEffect可以传入两个参数,第一个是必选参数,为function类型,是effect执行的内容,第二为可选参数,为数组类型,是判断是否执行该effect,若第二参数的数值发生变化,则执行。

  useEffect(()=>{
    console.log('current count:'+count)
  })

👆组件加载时、state变化时,都会执行console.log

  useEffect(()=>{
    console.log('first effect count:'+count)//new count
    return function cleanup(){console.log('first effect return count:'+count)}//old count
  })

👆组件加载时执行第一个console.log,state变化时,会先执行return的cleanup函数,打印上一次运行时的count,再执行第一个console.log。
注意!这里上一个运行时的意思是该effect上一次执行时的state,并非是上一个state,这么说有点绕,看一下这个例子👇

  useEffect(()=>{
    console.log('third effect count:'+count)
    return function cleanup(){console.log('third effect return count:'+count)}
  },[count>4?1:0])

👆假设你点击了8次,当你点第五次时,此时第二参数的内容从0变成了1,所以执行了该effect,打印了

third effect return count:0

third effect count:5

之后再也不执行该effect,直到将这个组件卸载时,才会执行该effect的cleanup函数,但打印的并不是想象中的 8 ,而是

third effect return count:5

既该effect的上一次运行时的state。

因为该特性,所以并不推荐第二参数传递[]来模拟componentDidMount 和componentWillUnmount,引用官网的原话

While passing [] is closer to the familiar componentDidMount and componentWillUnmount mental model, we suggest not making it a habit because it often leads to bugs, as discussed above. Don’t forget that React defers running useEffect until after the browser has painted, so doing extra work is less of a problem.

完整代码👇

//Count.jsx
import React, { useState, useEffect } from "react";

function Cunter() {
  const [count, setCount] = useState(0);

  useEffect(()=>{
    console.log('first effect count:'+count)
    return function cleanup(){console.log('first effect return cleanup')}
  },[])

  useEffect(()=>{
    console.log('second effect, current count:'+count)//new count
    return function cleanup(){console.log('second effect return count:'+count)}//old count
  })

  useEffect(()=>{
    console.log('third effect count:'+count)
    return function cleanup(){console.log('third effect return count:'+count)}
  },[count>4?1:0])

  return (
    <div className="count-box">
      <h1 className="title">点了{count}次</h1>
      <button onClick={() => {setCount(count + 1);}}>Click Me!</button>
    </div>
  );
}

export default Cunter;
//App.jsx
import React, { Component } from "react";
import Cunter from "./Cunter";
class App extends Component {
  constructor(props) {
    super(props);
    this.state = { show: true };
  }
  render() {
    return (
      <div>
        {this.state.show ? <Cunter /> : <p>cleanup</p>}
        <br/>
        <button  onClick={() => {this.setState({ show: false })}}>cleanup</button>
      </div>
    );
  }
}

export default App;
    原文作者:Y_qwq
    原文地址: https://segmentfault.com/a/1190000017947122
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞