【React Hooks】useEffect 用法

什么是副作用 effect

本来吃这个药💊,我只是想治个感冒而已,结果感冒虽然治好了,但是却过敏了。过敏便是副作用。

本来我只是想渲染DOM而已,可是当DOM渲染完成之后,我还要执行一段别的逻辑。这一段别的逻辑就是副作用。

在React中,如果利用得好,副作用可以帮助我们达到更多目的,应对更为复杂的场景。

  • 常见的副作用操作:
1. 发送ajax请求数据获取
2. 设置订阅
3. 手动更改真实DOM
4. 启动定时器/延时器

当然,如果hold不住,也会变成灾难,例如:

import React, { useState, useEffect } from 'react';
import './style.scss';
// 每个React组件初始化时,DOM都会渲染一次
export default function AnimateDemo() {
  const [counter, setCounter] = useState(0);

  // DOM渲染完成之后副作用执行
  useEffect(() => {
    setTimeout(() => {
      // 副作用:完成后的一秒钟,counter加1
      setCounter(counter + 1);
    }, 1000);
  });

  return (
    <div className="container">
      <div className="el">{counter}</div>
    </div>
  )
}
  • 猜猜最后的结果?
  • 结果就是:counter不停的在累加,陷入死循环
  • 分析下原因:
1. DOM渲染完成,副作用逻辑执行
2. 副作用逻辑执行过程中,修改了counter,而counter是一个state值
3. state改变,会导致组件重新渲染
4. 组件重新渲染,副作用再次逻辑执行
  • 要避免这种灾难怎么办?就要利用useEffect的第二个参数来帮助我们。
/*
	当第二个参数传入空数组,即没有传入比较变化的变量,
	则比较结果永远都保持不变,那么副作用逻辑就只能执行一次。
*/ 
useEffect(() => {
  setTimeout(() => {
    setCounter(counter + 1);
  }, 300);
}, []);

useEffect 基本用法

  • 语法和说明:
useEffect(()=>{
	// 在此可以执行任何带副作用操作
	return()=>{// 在组件卸载前执行
		// 在此做一些收尾工作,比如清除副作用
	}
},[stateValue])	// 如果指定的是[],回调函数只会在第一次render()后执行
  • useEffect 可以在组件渲染后实现各种不同的副作用。
  • 有些副作用可能需要清除,所以需要返回一个函数:
useEffect(() => {
    function handleStatusChange(status) {
      setIsOnline(status.isOnline);
    }

    ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
    return () => {
      ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
    };
  });
  • 其他的 effect 可能不必清除,所以不需要返回。
  useEffect(() => {
    document.title = `You clicked ${count} times`;
  });

useEffect 与生命周期

  • 类组件
//useState 使用状态值,第一个 hook
//1.引入useState  钩子
import React, { Component } from 'react';
class App extends Component {
  constructor(props) {
    super(props);
    this.state = { count: 10 }
  }
  //挂载后
  componentDidMount() {
    console.log("componentDidMount运行了");

  }
  //更新后
  componentDidUpdate() {
    console.log("componentDidUpdate 运行了");

  }
  //销毁前
  componentWillUnmount() {
    console.log("componentWillUnmount 运行了");

  }
  changeCount = () => {
    this.setState({ count: this.state.count + 1 })
  }
  render() {
    return (<div>类组件,钩子

      {this.state.count}
      <button onClick={this.changeCount}>+</button>
    </div>);
  }
}

export default App;
  • 使用useEffect Hook
//1.引入useState  钩子
import React, { useState, useEffect } from 'react';
function App() {

  const [count, setCount] = useState(10);
  const [age, setAge] = useState(18);
  const changeCount = () => {
    setCount(count + 1)
  }
  const changeAge = () => {
    setAge(20);
  }
  //1.useEffect 只有一个参数
  /*
  useEffect  只有一个参数的时候,相当于  componentDidMount  + componentDidUpdate
  */
  // useEffect(() => {
  //   console.log("useEffect 运行了");
  // })

  //2. useEffect  使用两个参数
  /*
  参数1:函数
  参数2:数组  ,依赖哪个数据发生变化时触发
  */
  //第二个参数是空数组  ,useEffect  相当于挂载后componentDidMount
  // useEffect(() => {
  //   console.log("useEffect 运行了");
  // }, [])

  //3.第二个参数不是空数组 ,定义了触发这个钩子函数的依赖项,
  //组件挂载时触发一次
  //依赖项发生变化时,该钩子函数也会被调用
  //
  // useEffect(() => {
  //   console.log("useEffect 运行了 ,count: " + count);
  // }, [count])

  //4.相当于卸载前的钩子函数
  //当 useEffect 的第二个参数为空数组时,在函数中的return 的函数里执行的操作相当于卸载componentWillUnmount
  useEffect(() => {
    console.log("挂载运行了");
    //卸载:清除定时器、清除绑定事件,结束未完成的axios数据获取
    return () => {
      console.log("卸载钩子函数运行了 ");
    }
  }, [])


  return (
    <div>类组件,钩子

      {count}
      <button onClick={changeCount}>+</button>

      年龄:{age}
      <button onClick={changeAge}>改变年龄</button>

    </div>
  )

}
export default App;
  • 使用useEffect获取数据
//useState 使用状态值,第一个 hook
//1.引入useState  钩子
import React, { useState, useEffect } from 'react';
import axios from 'axios';
function App() {
  //将获取数据封装为函数
  function getData() {
    return axios.get("http://www.51houniao.com/product/product/guessYouLike").then(res => {
      return res;
    })
  }

  //相当于挂载
  useEffect(async () => {
    const data = await getData();
    console.log(data);
  }, [])
  return (
    <div>
      <h2>获取数据</h2>
    </div>
  )
}
export default App;
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: React Hooks中的useEffect是一个函数,用于在函数组件中处理副作用。它接收两个参数:一个函数和一个依赖数组。当依赖数组中的任何一个值发生变化时,useEffect中的函数就会被调用。这个函数可以用来执行一些副作用操作,比如发送网络请求、订阅事件、更新DOM等。在函数组件中使用useEffect可以替代类组件中的生命周期方法。 ### 回答2: React hooks是React 16.8版本新增的特性,可以让函数组件具有类组件的一些功能,其中包括useEffect这一HookuseEffect可以让我们在函数组件中实现类似于类组件中生命周期函数的效果。 useEffect接收两个参数,第一个参数是一个回调函数,第二个参数是一个数组。回调函数在组件每次渲染后都会执行,类似于componentDidUpdate函数。如果数组为空,回调函数仅在组件首次渲染时执行,类似于componentDidMount函数。如果数组不为空,回调函数仅在数组中的值有变化时执行,类似于shouldComponentUpdate函数。 useEffect可以用来处理一些副作用操作,比如数据的异步获取和更新、页面的滚动位置、事件的监听等等。在回调函数中进行的操作可能会影响到组件的状态、渲染等方面,所以我们需要使用useEffect来进行监控和管理。在回调函数中可以返回一个函数,这个函数在组件不再需要该效果时执行,可以用于取消监听等清理操作。 需要注意的是,useEffect在每次渲染后都会执行,如果回调函数中有一些操作比较耗时,则会对性能造成影响。我们可以使用useMemo、useCallback等Hook来优化这些操作的性能。此外,在数组中传递的参数需要谨慎选择,不恰当的选择可能会导致useEffect失效。 总之,useEffectReact hooks中非常重要的一个Hook,可以用来做很多副作用操作。只要我们掌握了useEffect用法和注意事项,就能更好地管理和维护函数组件的状态和渲染。 ### 回答3: React Hooks是React16.8引入的新特性,大大简化了React组件的编写方式,其中useEffectReact Hooks中的一个非常重要的Hook,它允许我们在函数组件中执行任意一段副作用代码。 在React环境中,副作用通常涉及向服务器请求数据、处理DOM元素以及处理其他一些与UI渲染无关的操作。这些操作称为副作用,因为它们可能会对其他部分的应用程序的状态或行为产生影响,我们需要小心处理这些副作用。 使用useEffect可以在组件渲染时执行副作用,而且可以灵活地在组件生命周期中、或是在state或props发生变化时进行副作用的更新。 useEffect使用一个回调函数作为第一个参数,并在回调函数中定义需要执行的副作用代码。useEffect还可以有第二个参数,是一个数组,用于定义何时更新副作用的条件。如果第二个参数为空数组,那么副作用只会在组件挂载或卸载时执行。如果第二个参数包含依赖值,那么当依赖值有变化时,副作用也会被重新执行。 通过使用useEffect函数,我们可以在React函数组件中编写可以执行副作用代码的简洁股票。同时,也可以通过控制副作用代码的执行时机,避免副作用对应用程序产生不必要的影响。因此,useEffect已经成为React Hooks开发中的必不可少的一部分。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一颗不甘坠落的流星

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值