一直以来对于函数式组件执行顺序都有一点小疑惑,在这里小记一下。废话不多说,直接上代码:
function Test(props) {const [count, setCount] = useState(0)useEffect(() => {console.log('2222')})console.log('1111')return (<>{count}{console.log('3333')} {/*不规范*/}<button onClick={() => setCount(count + 1)}>+1</button></>)}/*执行顺序:111133332222*/
初次渲染组件和点击按钮使得组件重新刷新,打印结果都如上所示。可得结论,写在函数式组件体的console.log最先执行,其次是渲染时的console.log,最后由于useEffect是在浏览器渲染完试图异步执行,因此useEffect中的console.log最后执行。
利用这一特性,我们可以在函数式组件中获取上一轮的 props 或 state。
const [count, setCount] = useState(0);const prevCountRef = useRef();useEffect(() => {// thirdprevCountRef.current = count;});// firstconst prevCount = prevCountRef.current;return (<><h1>{/*second*/}Now: {count}, before: {prevCount}</h1><button onClick={() => setCount(count + 1)}>+1</button></>);
利用useEffect中回调最后执行的特性。
当然,我们也可以封装成一个hook:
function Test(props) {const [count, setCount] = useState(0);const prevCount = usePrevious(count)return (<><h1>Now: {count}, before: {prevCount}</h1><button onClick={() => setCount(count + 1)}>+1</button></>);}function usePrevious(value) {const ref = useRef();console.log('222')useEffect(() => {ref.current = value;});return ref.current;}
