本来吃这个药,我只是想治个感冒而已,结果感冒虽然治好了,但是却过敏了。过敏便是副作用。
本来我只是想渲染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>
)
}
1. DOM渲染完成,副作用逻辑执行
2. 副作用逻辑执行过程中,修改了counter,而counter是一个state值
3. state改变,会导致组件重新渲染
4. 组件重新渲染,副作用再次逻辑执行
/*
当第二个参数传入空数组,即没有传入比较变化的变量,
则比较结果永远都保持不变,那么副作用逻辑就只能执行一次。
*/
useEffect(() => {
setTimeout(() => {
setCounter(counter + 1);
}, 300);
}, []);
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);
};
});
useEffect(() => {
document.title = `You clicked ${count} times`;
});
//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;
//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;
//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;