useState 保存组件状态和useEffect 处理副作用

Posted 前端e站

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了useState 保存组件状态和useEffect 处理副作用相关的知识,希望对你有一定的参考价值。

前面介绍了React hooks的一些概念及其用法,接下里就来学习一下使用方法。这一节主要介绍useState 保存组件状态useEffect 处理副作用

useState 保存组件状态 

在类组件中,我们使用  this.state  来保存组件状态,并对其修改触发组件重新渲染。比如下面这个简单的计数器组件,很好诠释了类组件如何运行: 

import React from "react";
class App extends React.Component 
  constructor(props) 
    super(props);
    this.state = 
      count: 0,
      name: "alife"
    ;
  
  render() 
    const  count  = this.state;
    return (
      <div>
        Count: count
        <button onClick=() => this.setState( count: count + 1 )>+</button>
        <button onClick=() => this.setState( count: count - 1 )>-</button>
      </div>
    );
  

 一个简单的计数器组件就完成了,而在函数组件中,由于没有 this 这个黑魔法,React 通过 useState 来帮我们保存组件的状态。

通过传入 useState 参数后返回一个带有默认状态和改变状态函数的数组。通过传入新状态给函数来改变原本的状态值。值得注意的是 useState 不帮助你处理状态,相较于 setState 非覆盖式更新状态,useState 覆盖式更新状态,需要开发者自己处理逻辑。(代码如上)

似乎有个 useState 后,函数组件也可以拥有自己的状态了,但仅仅是这样完全不够。

useEffect 处理副作用

函数组件能保存状态,但是对于异步请求,副作用的操作还是无能为力,所以 React 提供了 useEffect 来帮助开发者处理函数组件的副作用,在介绍新 API 之前,我们先来看看类组件是怎么做的:

import React,  Component  from "react";
class App extends Component 
  state = 
    count: 1
  ;
  componentDidMount() 
    const  count  = this.state;
    document.title = "componentDidMount" + count;
    this.timer = setInterval(() => 
      this.setState(( count ) => (
        count: count + 1
      ));
    , 1000);
  
  componentDidUpdate() 
    const  count  = this.state;
    document.title = "componentDidMount" + count;
  
  componentWillUnmount() 
    document.title = "componentWillUnmount";
    clearInterval(this.timer);
  
  render() 
    const  count  = this.state;
    return (
      <div>
        Count:count
        <button onClick=() => clearInterval(this.timer)>clear</button>
      </div>
    );
  

在例子中,组件每隔一秒更新组件状态,并且每次触发更新都会触发 document.title 的更新(副作用),而在组件卸载时修改 document.title(类似于清除)

从例子中可以看到,一些重复的功能开发者需要在 componentDidMount 和 componentDidUpdate 重复编写,而如果使用 useEffect 则完全不一样。

import React,  useState, useEffect  from "react";
let timer = null;
function App() 
  const [count, setCount] = useState(0);
  useEffect(() => 
    document.title = "componentDidMount" + count;
  ,[count]);
 
  useEffect(() => 
    timer = setInterval(() => 
      setCount(prevCount => prevCount + 1);
    , 1000);
    // 一定注意下这个顺序:
    // 告诉react在下次重新渲染组件之后,同时是下次执行上面setInterval之前调用
    return () => 
      document.title = "componentWillUnmount";
      clearInterval(timer);
    ;
  , []);
  return (
    <div>
      Count: count
      <button onClick=() => clearInterval(timer)>clear</button>
    </div>
  );

我们使用 useEffect 重写了上面的例子,useEffect 第一个参数接收一个函数,可以用来做一些副作用比如异步请求,修改外部参数等行为,而第二个参数称之为dependencies,是一个数组,如果数组中的值变化才会触发 执行useEffect 第一个参数中的函数。返回值(如果有)则在组件销毁或者调用函数前调用。

  • 比如第一个 useEffect 中,理解起来就是一旦 count 值发生改变,则修改 documen.title 值;
  • 而第二个 useEffect 中传递了一个空数组[],这种情况下只有在组件初始化或销毁的时候才会触发,用来代替 componentDidMount 和 componentWillUnmount,慎用;
  • 还有另外一个情况,就是不传递第二个参数,也就是useEffect只接收了第一个函数参数,代表不监听任何参数变化。每次渲染DOM之后,都会执行useEffect中的函数。

基于这个强大 Hooks,我们可以模拟封装出其他生命周期函数,比如 componentDidUpdate 代码十分简单。

现在我们有了 useState 管理状态,useEffect 处理副作用,异步逻辑,学会这两招足以应对大部分类组件的使用场景。

以上是关于useState 保存组件状态和useEffect 处理副作用的主要内容,如果未能解决你的问题,请参考以下文章

useState 保存组件状态和useEffect 处理副作用

useState和useEffect

React useState 和 useEffect 混淆

useEffect 中的 useState 不更新状态

HOOK—useState、useEffect的使用

useState 在 useEffect 中定义后保持初始状态