Skip to content
New issue

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

React useRef 实践指南 #390

Open
yangchch6 opened this issue Aug 26, 2020 · 0 comments
Open

React useRef 实践指南 #390

yangchch6 opened this issue Aug 26, 2020 · 0 comments

Comments

@yangchch6
Copy link

大家应该熟悉 React ref,它可以用来获取组件实例对象或者是DOM对象。而 useRef 这个 hooks 函数,除了传统的用法之外,还可以“跨渲染周期”保存数据。

useRef 传统用法

获取组件实例对象或者是DOM对象

import React, { useState, useEffect, useRef, useMemo } from 'react';

const Demo = () => {
    const [count, setCount] = useState(0);

    const doubleCount = useMemo(() => {
        return 2 * count;
    }, [count]); // 第二个参数为[]不会更新

    const couterRef = useRef();

    useEffect(() => {
        document.title = `The value is ${count}`;
        console.log(couterRef.current);
    }, [count]); // 第二个参数为[]不会更新
    
    return (
        <>
            <button ref={couterRef} onClick={() => {setCount(count + 1)}}>Count: {count}, double: {doubleCount}</button>
        </>
    );
}
export default Demo

代码中用 useRef 创建了 couterRef 对象,并将其赋给了 button 的 ref 属性。这样,通过访问 couterRef.current 就可以访问到 button 对应的 DOM 对象。

useRef 保存数据

在一个组件中,state 属性可以跨渲染周期,也就是在组件被多次渲染之后依旧不变。但是,state 的问题在于一旦修改了它就会造成组件的重新渲染。

而使用 useRef 来跨越渲染周期存储数据,对它修改是不会引起组件渲染的。

示例1: 保存定时器ID

import React, { useState, useEffect, useMemo, useRef } from 'react';

export default function App(props){
    const [count, setCount] = useState(0);

    const doubleCount = useMemo(() => {
        return 2 * count;
    }, [count]);

    const timerID = useRef();
    
    useEffect(() => {
        timerID.current = setInterval(()=>{
            setCount(count => count + 1);
        }, 1000); 
    }, []);
    
    useEffect(()=>{
        if(count > 10){
            clearInterval(timerID.current);
        }
    });
    
    return (
        <>
            <button onClick={() => {setCount(count + 1)}}>Count: {count}, double: {doubleCount}</button>
        </>
    );
}

在上面的例子中,我用 ref 对象的 current 属性来存储定时器的ID,这样便可以在多次渲染之后依旧保存定时器ID,从而能正常清除定时器。

示例2: 保存上一次的值

import React, { useState, useEffect, useRef } from 'react';

function usePrevious(value){
    const ref = useRef()
    useEffect(() => {
        ref.current = value
    })
    return ref.current
}

const Counter = () => {
    const [count, setCount] = useState(0)
    const preCount = usePrevious(count)
    useEffect(() => {
        setTimeout(() => setCount(10), 1000)
    })
    return <h1> Now: {count}, before: {preCount}</h1>
}

export default Counter

上面代码中,使用了 ref 对象的 current 属性来存储 count 被修改前的值

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant