- useEffect 执行的是副作用
- useEffect 不同的事情分开放,分开声明 useEffect
- 不关心生命周期函数,统一在渲染后调用
- 第二个参数可选,是数组,在数组每一项都不变得情况下,才不会渲染
- 阻止 useEffect再次渲染
- 找到依赖的参数,避免重复计算
- 第二个参数 useEffect的精髓
- useEffect会比较前一次渲染和后一次渲染的值
- useEffect的不作为componentDidUnmount的话,传入第二个参数时一定注意
- 第二个参数不能为引用类型,数组或对象;引用类型比较不出来数据的变化,会造成死循环
副作用:都是围绕组件的渲染和重新渲染
- 精准控制第二个参数,防止组件或事件重复渲染
useEffect(() => {}, [])
- 副作用 https://www.jianshu.com/p/dffa57f8dfcf
- 绑定事件
- 网络请求
- 访问 DOM ```jsx function App () {
useEffect(() => { // componentDidMount return () => { // componentWillUnmount } })
let renderCounter = useRef(0) renderCounter.current + 1
useEffect(() => { if (renderCounter > 1) { // componentDidUpdate // 副作用 } })
useEffect(() => { fetch(‘/api/list’).then() }, [])
useEffect(() => { document.title = count }, [count]) }
- 使用setInterval或者setTimeout的,就简单一点,直接 clearInterval()
- 添加监听事件addEventListener的,在函数中 removeEventListener
- axios请求,取消请求
```jsx
useEffect(() => {
const source = axios.CancelToken.source();
const fetchData = async () => {
const response = await Axios.get("/users", {
cancelToken: source.token
});
};
fetchData()
return () => {
source.cancel();
};
}, [user.id]);
副作用对应的就是纯函数
class 类组件的副作用
- 绑定事件
- 网络请求
- 访问 DOM
- state状态的改变
- 生命周期
- constructor构造函数等都可以看做是副作用
副作用的时机
副作用 useEffect代替
- mount 之后 componentDidMount
- update 之后 componentDidUpdate
- unmount 之前 componentWillUnmount
useEffect没有参数
- useEffect可以执行多个,在一个函数里面可以写多个 useEffect
- 没有参数,页面每个事件,例如 onClick,onHover 都会触发 useEffect
如果在里面 调用 setState会死循环,相当于 componentDidUpdate
function App(props) {
没有参数,页面每个事件,例如 onClick,onHover 都会触发 useEffect
如果在里面 调用 setState会死循环,相当于 componentDidUpdate
useEffect(() => {
console.log('useEffect')
})
}
useEffect参数是空数组
第二个参数是:空数组,只会执行一次
等价于 componentDidMount
function App(props) {
useEffect(() => {
console.log('useEffect')
}, [])
}
useEffect数组有多个参数
第二个参数是多个值的数组,如果依赖项改变,useEffect就会触发
useEffect(() => {
console.log('useEffect')
}, [id, name])
useEffect执行异步
- useEffect 可以执行异步,但是不支持 async & await
- useEffect要么返回一个函数,要么什么都不返回
useEffect不支持关键字 async
- 因为 async将返回一个 promise,useEffect原本的返回类型,将被 Promise代替
因为 promise既不是函数,也不是 null所以 ```jsx 正确的用法 useEffect(() => { async function getList() { const res = await fetch(‘api/list/‘ + id) const data = await res.json()
setState(data) }
getList() }, [id])
useEffect(() => { const getList = async () => { const res = await fetch(‘api/list/‘ + id) const data = await res.json()
setState(data)
}
getList() }, [id])
正确的用法 async function getList(id) { const res = await fetch(‘api/list/‘ + id) const data = await res.json() setState(data) }
useEffect(() => { getList(id) }, [id])
错误的异步用法:❌
```jsx
useEffect( async() => {
const res = await fetch('api/list/' + id)
const data = await res.json()
}, [id])
强制更新值
function Counter() {
const [count, setCount] = useState(0)
const [update, setUpdate] = useState(0)
function forceUpdate () {
setUpdate(update => update + 1)
}
const prevCountRef = useRef()
useEffect(() => {
prevCountRef.current = count
})
const prevCount = prevCountRef.current
return <h1>新值:{count}, before: {prevCount}</h1>
}
useLayoutEffect
- 在所有 DOM加载完成,才执行 useLayoutEffect
- 通常在 useLayoutEffect里面做 DOM相关操作 ```jsx useLayoutEffect(() => {
}, []) ```
纯函数
pure-function
- 给一个函数同样的参数, name这个函数永远发那会同样的值
- 给一个固定的输入,就会有一个固定的输出
- 函数式编程理念
- 给 React组件输入相同的 props参数,渲染的UI永远是一样的
- 副作用与纯函数相反,指的是一个函数处理了与返回值无关的事情
- 例如:ajax异步请求书
- 修改了 DOM
- console.log 打印了内容等都是副作用
- 输入参数一样,输出结果不一样的情况,就是副作用
- 副作用会给系统添加不可控因素
- 没有必要去避免副作用,要注意代码的健壮性
二元一次方程就是纯函数
- 数学中的函数: y = f(x)
- 函数的定义:
- 在两个非空集合中,存在一种关系,可以让输入值结合中的每项元素,
- 皆对应唯一一项输出值集合中的元素