We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
每日一题会在下午四点在交流群集中讨论,五点小程序中更新答案 欢迎大家在下方发表自己的优质见解 二维码加载失败可点击 小程序二维码
每日一题会在下午四点在交流群集中讨论,五点小程序中更新答案 欢迎大家在下方发表自己的优质见解
useEffect(didUpdate, deps); const memoizedCallback = useCallback(() => { doSomething(params); }, deps); const memoizedValue = useMemo(() => computerExpensiveValue(params), deps);
useEffect 一般用于处理状态更新导致的 side effects。虽然说不提倡面向生命周期函数编程,但是在没有熟练掌握 useEffect 的时候,类比 Class Component 的生命周期函数最能帮助我们快速上手。
useEffect 可以看做是 componentDidMount/componentDidUpdate/componentWillUnmount 这三个生命周期函数的替代。
componentDidMount/componentDidUpdate/componentWillUnmount
看下官网提供的例子,可以非常全面的展示 useEffect 的使用方式:
import React, { useState, useEffect } from "react"; // 该组件定时从服务器获取好友的在线状态 function FriendStatus(props) { const [isOnline, setIsOnline] = useState(null); useEffect(() => { function handleStatusChange(status) { setIsOnline(status.isOnline); } // 在浏览器渲染结束后执行 ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange); // 在每次渲染产生的 effect 执行之前执行 return function cleanup() { ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange); }; // 只有 props.friend.id 更新了才会重新执行这个 hook }, [props.friend.id]); if (isOnline === null) { return "Loading..."; } return isOnline ? "Online" : "Offline"; }
useEffect 是官方推荐拿来代替 componentDidMount/componentDidUpdate/componentWillUnmount 这三个生命周期函数的,但是它们并不是完全等价的,useEffect 是在浏览器渲染结束之后才执行的,而这三个生命周期函数是在浏览器渲染之前同步执行的,React 还有一个官方的 hook 是完美等价于这三个生命周期函数的,叫 useLayoutEffect。
useEffect 和 useLayoutEffect 的区别来看一个例子:
const App = () => { const [count, setCount] = React.useState(0); React.useEffect(() => { // 耗时 300 毫秒的计算 const start = +new Date(); while (+new Date() - start <= 300) { continue; } if (count === 0) { setCount(Math.random()); } }, [count]); const handleClick = React.useCallback(() => setCount(0), []); return <button onClick={handleClick}>{count}</button>; };
效果如下:
如果换成 useLayoutEffect,得到的效果是:
这个例子可以很明显看出 useEffect 和 useLayoutEffect 之间的区别,useEffect 是在浏览器重绘之后才异步执行的,所以点击按钮上的数字会先变成 0,再变成一个随机数;而 useLayoutEffect 是在浏览器重绘之前同步执行的,所以两次 setCount 合并到 300 毫秒后的重绘里了。
因为 useEffect 不会阻塞浏览器重绘,而且平时业务中我们遇到的绝大多数场景都是时机不敏感的,比如取数、修改 dom、事件触发/监听...,所以首推使用 useEffect 来处理 side effects,性能上表现的更好一些。
didUpdate 是一个包含命令式,且可能有副作用代码的函数
didUpdate 是组件渲染成功且 deps 依赖参数发生变化时执行的函数。
didUpdate 可以没有返回值,只是执行 didUpdate 的内容。
但是当 didUpdate 有返回值的时候,返回值必须是一个可执行的函数,目的是用于清除 didUpdate 执行过程中产生的订阅或者计时器等资源。同时如果 didUpdate 多次触发,则在每次重新执行前都会先执行返回的可执行函数。(官方称之为清除 Effect)
useEffect(() => { const timer = setInterval(() => { console.log("effect"); }, 1000); return () => { // 清除定时器 clearInterval(timer); }; });
有人可能误认为 useCallback 可以用来解决创建函数造成的性能问题,其实恰恰相反。单个组件来看,useCallback 只会更慢,因为 inline 函数是无论如何都会创建的,还增加了 useCallback 内部对 inputs 变化的检测。
function A() { const cb = () => {}; /* 创建了 */ } function B() { const cb = React.useCallback(() => {} /* 还是创建了 */, [a, b]); }
useCallback 的真正目的是在于缓存每次渲染时 inline callback 的实例,这样方便配合上子组件的 shouldComponentUpdate 或者 React.memo 起到减少不必要的渲染的作用。需要注意的是 React.memo 和 React.useCallback 一定要配对使用。缺了一个可能导致性能不升反降。毕竟无意义的浅比较也是消耗那么一点点的性能。
React.memo
React.useCallback
返回一个 memoized 的回调函数,即返回一个函数的句柄,等同于函数的变量,因此 useCallback 的作用在于利用 memoize 减少无效的 re-render,来达到性能优化的作用。
useMemo 是拿来保持一个对象引用不变的。useMemo 和 useCallback 都是 React 提供来做性能优化的。比起 classes,Hooks 给了开发者更高的灵活度和自由,但是对开发者要求也更高了,因为 Hooks 使用不恰当很容易导致性能问题。
返回一个 memoized 值,useMemo 函数每当 deps 发生变化时都会调用 computeExpensiveValue 的内容,这是与 useCallback 最大的不同,useCallback 不执行 doSomething 的内容,只是重新刷新函数句柄。
句柄 官方上有这样一个等式:useCallback(fn,deps) 相当于 useMemo(()=>fn,deps)。就是 deps 发生变化时,useCallback 返回的是一个可执行的 fn 的句柄,而 useMemo 则是执行()=>fn,但是因为返回的是 fn 函数,因此当调用这种时,其实执行的是相同的 fn 函数内容。
useCallback(fn,deps)
useMemo(()=>fn,deps)
()=>fn
The text was updated successfully, but these errors were encountered:
你好,扫描不了二维码
Sorry, something went wrong.
componentWillReceiveProps 这个react的生命周期现在在函数式组件中 哪些地方将会用到
No branches or pull requests
扫描下方二维码,收藏关注,及时获取答案以及详细解析,同时可解锁800+道前端面试题。
一、定义
1.1 useEffect
useEffect 一般用于处理状态更新导致的 side effects。虽然说不提倡面向生命周期函数编程,但是在没有熟练掌握 useEffect 的时候,类比 Class Component 的生命周期函数最能帮助我们快速上手。
useEffect 可以看做是
componentDidMount/componentDidUpdate/componentWillUnmount
这三个生命周期函数的替代。看下官网提供的例子,可以非常全面的展示 useEffect 的使用方式:
1.2 useLayoutEffect
useEffect 是官方推荐拿来代替
componentDidMount/componentDidUpdate/componentWillUnmount
这三个生命周期函数的,但是它们并不是完全等价的,useEffect 是在浏览器渲染结束之后才执行的,而这三个生命周期函数是在浏览器渲染之前同步执行的,React 还有一个官方的 hook 是完美等价于这三个生命周期函数的,叫 useLayoutEffect。useEffect 和 useLayoutEffect 的区别来看一个例子:
效果如下:
如果换成 useLayoutEffect,得到的效果是:
这个例子可以很明显看出 useEffect 和 useLayoutEffect 之间的区别,useEffect 是在浏览器重绘之后才异步执行的,所以点击按钮上的数字会先变成 0,再变成一个随机数;而 useLayoutEffect 是在浏览器重绘之前同步执行的,所以两次 setCount 合并到 300 毫秒后的重绘里了。
因为 useEffect 不会阻塞浏览器重绘,而且平时业务中我们遇到的绝大多数场景都是时机不敏感的,比如取数、修改 dom、事件触发/监听...,所以首推使用 useEffect 来处理 side effects,性能上表现的更好一些。
didUpdate 是一个包含命令式,且可能有副作用代码的函数
didUpdate 是组件渲染成功且 deps 依赖参数发生变化时执行的函数。
didUpdate 可以没有返回值,只是执行 didUpdate 的内容。
但是当 didUpdate 有返回值的时候,返回值必须是一个可执行的函数,目的是用于清除 didUpdate 执行过程中产生的订阅或者计时器等资源。同时如果 didUpdate 多次触发,则在每次重新执行前都会先执行返回的可执行函数。(官方称之为清除 Effect)
1.2 useCallback
有人可能误认为 useCallback 可以用来解决创建函数造成的性能问题,其实恰恰相反。单个组件来看,useCallback 只会更慢,因为 inline 函数是无论如何都会创建的,还增加了 useCallback 内部对 inputs 变化的检测。
useCallback 的真正目的是在于缓存每次渲染时 inline callback 的实例,这样方便配合上子组件的 shouldComponentUpdate 或者
React.memo
起到减少不必要的渲染的作用。需要注意的是React.memo
和React.useCallback
一定要配对使用。缺了一个可能导致性能不升反降。毕竟无意义的浅比较也是消耗那么一点点的性能。返回一个 memoized 的回调函数,即返回一个函数的句柄,等同于函数的变量,因此 useCallback 的作用在于利用 memoize 减少无效的 re-render,来达到性能优化的作用。
1.3 useMemo
useMemo 是拿来保持一个对象引用不变的。useMemo 和 useCallback 都是 React 提供来做性能优化的。比起 classes,Hooks 给了开发者更高的灵活度和自由,但是对开发者要求也更高了,因为 Hooks 使用不恰当很容易导致性能问题。
返回一个 memoized 值,useMemo 函数每当 deps 发生变化时都会调用 computeExpensiveValue 的内容,这是与 useCallback 最大的不同,useCallback 不执行 doSomething 的内容,只是重新刷新函数句柄。
The text was updated successfully, but these errors were encountered: