[Note] React: forwardRef


Posted by urlun0404 on 2022-10-18

有時候會希望可以不透過state、props傳遞的方式呼叫child component內部的function,這種方式稱為imperative approach。

以下示範如何用 refforwardRefuseImperativeHandle hook 達成:

// Form.js (parent component)
import {useState, useRef} from 'react'

export default function Form(){
    const [emailIsValid, setEmailIsValid] = useState(false);
    const [passwordIsValid, setPasswordIsValid] = useState(false);

    const emailRef = useRef();
    const passwordRef = useRef();

    // * Call focus function (alias: activate) inside <Input/>
    useEffect(()=>{
        if(!emailIsValid){
            emailRef.current.activate();   // *
        } else{
            passwordRef.current.activate();   // *
        }
    }, []);

    return (
        <form>
            <Input
                ref={emailRef}
                id="email"
                name="email"
                type="text"
            >
            <Input
                ref={passwordRef}
                id="password"
                name="password"
                type="password"
            >
        </form>
    );
}


<Input> 實際上是一個用來包裝 <label><input> 標籤的component:

// Input.js (child component)
import { useRef, useImperativeHandle } from 'react'

// ref is the ref defined outside and "actually" used via fowardRef
export default function React.forwardRef(Input(props, ref){

    const inputRef = useRef();

    const focus = () => {
        inputRef.current.focus();
    }


    // Manipulate something inside imperatively
    // (NOT through regular state or props management)
    useImperativeHandle(ref, () => {
        return {
            // A translation object that let something that can be used outside
            activate: focus
        }
    });


    return (
        <>
            <label>{props.name}</label>
            <input
                ref={inputRef}   // Ref defined inside
                id={props.id}
                name={props.name}
                type={props.type}
            >
        </>
    );
});


重點

  1. Imperative approach 要用 useImperativeHandle hook;
  2. useImperativeHandle 的第一個引數是定義在parent component的ref (e.g., emailRef、passwordRed),第二個引數則要傳入一個function並return一個特別的object,這個object可以放一些要被parent component使用的東西,如範例中的focus函式可以透過 activate 名稱呼叫;
  3. 外部ref並非props的一部分,要額外跟props一起傳入,如範例中(props, ref)ref
  4. 此外,要真正能使用外部ref,必須將child component用 forwardRef 包起來,forwardRef 會綁定外部ref並回傳一個component。



References
React - The Complete Guide (incl Hooks, React Router, Redux)


#frontend #React #ref #forwardRef #note







Related Posts

The way open PDF in android.

The way open PDF in android.

Day02 VGGNet (CNN延伸應用)

Day02 VGGNet (CNN延伸應用)

203. Remove Linked List Elements

203. Remove Linked List Elements


Comments