useEffect代替常用生命周期函数
原始生命周期函数
componentDidMount
componentDidUpdate
componentWillUnmount
采用原始的方式把计数器的Demo增加两个生命周期函数componentDidMount和componentDidUpdate。
分别在组件第一次渲染后在浏览器控制台打印出计数器结果和在每次计数器状态发生变化后打印出结果。
代码如下:
import React, { Component } from 'react'; class Example3 extends Component { constructor(props) { super(props); this.state = { count:0 } } componentDidMount(){ console.log(`ComponentDidMount=>You clicked ${this.state.count} times`) } componentDidUpdate(){ console.log(`componentDidUpdate=>You clicked ${this.state.count} times`) } render() { return ( <div> <p>You clicked {this.state.count} times</p> <button onClick={this.addCount.bind(this)}>Chlick me</button> </div> ); } addCount(){ this.setState({count:this.state.count+1}) } } export default Example3;
React首次渲染和之后的每次渲染都会调用一遍useEffect函数,而之前我们要用两个生命周期函数分别表示首次渲染(componentDidMonut)和更新导致的重新渲染(componentDidUpdate)。
组件中经常用到componentWillUnmount生命周期函数(组件将要被卸载时执行)。比如我们的定时器要清空,避免发生内存泄漏;比如登录状态要取消掉,避免下次进入信息出错。
app.js
import React, { useState , useEffect } from 'react'; import { BrowserRouter as Router, Route, Link } from "react-router-dom" function Index() { useEffect(()=>{ console.log('useEffect=>老弟你来了!Index页面') return ()=>{ console.log('老弟,你走了!Index页面') } },[]) return <h2>JSPang.com</h2>; } function List() { useEffect(()=>{ console.log('useEffect=>老弟,你来了!List页面') return ()=>{ console.log('老弟,你走了!List页面') } }) return <h2>List-Page</h2>; } function App(){ const [ count , setCount ] = useState(0); useEffect(()=>{ console.log(`useEffect=>You clicked ${count} times`) return ()=>{ console.log('====================') } },[count]) return ( <div> <p>You clicked {count} times</p> <button onClick={()=>{setCount(count+1)}}>click me</button> <Router> <ul> <li> <Link to="/">首页</Link> </li> <li><Link to="/list/">列表</Link> </li> </ul> <Route path="/" exact component={Index} /> <Route path="/list/" component={List} /> </Router> </div> ) } export default App;
index.js
import React from "react"; import {render} from "react-dom" import App from "./components/app" import {BrowserRouter} from "react-router-dom"; //渲染组件,我们使用react-router组件渲染组件时需要使用路由器组件标签,我们可以使用"<BrowserRouter>"或者是"<HashRouter>"。但需要注意哟,这是一个SPA应用哟~ render( ( <BrowserRouter> <App /> </BrowserRouter> ), document.getElementById("root") )
PS:
useEffect的第二个参数:
实现类似componentWillUnmount的效果,它是一个数组,数组中可以写入很多状态对应的变量,意思是当状态值发生变化时,我们才进行解绑。
如果我们想每次count发生变化,我们都进行解绑,只需要在第二个参数的数组里加入count变量就可以了但是当传空数组[]时,就是当组件将被销毁时才进行解绑,这也就实现了componentWillUnmount的生命周期函数。
对React Hooks(useState和useEffect) 的总结思考
一、为什么用React Hooks(面向生命周期编程变成了面向业务逻辑编程)
Hooks是React16.8版本后新增加的特性,目的是让你用函数组件的写法代替原来的类组件写法,同时让函数组件支持state,同时用useEffect代替原来的生命周期的业务功能编写代码
风格,目的就是解决原来用class写组件的痛点,痛点有哪些自行查阅资料,主要有:
(1)选择性烦恼:是使用状态组件还是无状态组件? 拥有了hooks后,现在一切组件均是Function。
(2)搞不清生命周期的钩子函数? 拥有了hooks后,生命周期钩子函数可以先丢一边了。
(3)组件的this搞晕了?拥有了hooks后,不需面对this.
二、useState理解
1.useState是异步的,定义方法(语法叫数组解构写法),例如:
// 声明一个叫 “count” 的 state 变量 const [count, setCount] = useState(0); // 更新state <button onClick={() => setCount(count + 1)}> Click me </button>
2. state变量可以定义多个,也可以存储对象和数组,这边有一个规则:它总是替换它,而不象class一样合并它,即有闭包的概念。
三、useEffect的理解(原则:让你忘记类组件的生命周期的函数写法)
useEffect出现的需求背景:我们只想在 React 更新 DOM 之后运行一些额外的代码 (所以叫副作用函数)
(一) 它是一个钩子函数的定义,即对于dom的渲染后会产生相应的副作用(这个副作用中定义相关的功能),达于原来类组件的对生命周期函数一样的应用效果,但比它更灵活省事。
(二)定义一个useEffect主要分为四种定义方法(总结:需不要return,需不要第二个参数,第二个参数要不要[]):
- 1.每次渲染都要执行:则第二个参数不需要。
- 2.在组件销毁或者调用函数前调用。: 则第一个参数中增加return语句。
- 3.只在组件挂载时执行一次:则第二个参数用空数组:[].
- 4.只在某一个state或者prop值发生变化后,才执行,则第二个参数[变量名]。
(三)useEffect可以定义多个,把功能实现进行分离。
(四)useEffect 使用规则:
- 1.只在最顶层使用 Hook
- 2.只在 React 函数中调用 Hook
四、useState和useEffect声明时有先后顺序
产生的结果是不一样,所以根据业务需要灵活确定他们先后顺序的组合。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持阿兔在线工具。