部落格

不定期分享技術文章

  • article-useRef 和 forwardRef

    2024/6/11

    React Hooks
    useRef 和 forwardRef

    為什麼要使用 useRefforwardRef

    useRef

    1. 可以維持元件的狀態,並且不會觸發重新渲染。
    2. 可以用來控制DOM元素,例如:focus、scroll、play、pause等。
      程式碼範例如下:
    function MyComponent() {
      const inputRef = useRef(null);
    
      useEffect(() => {
        inputRef.current.focus(); // 自動聚焦
      }, []);
    
      return <input ref=&#123;inputRef&#125; />;
    &#125;
    

    forwardRef

    1. 可以將ref傳遞到子元件。
    2. 如果不使用forwardRef,React會報錯
      程式碼範例如下:
    // 定義一個 FancyButton 組件,使用 forwardRef 將 ref 傳遞下去
    const FancyButton = forwardRef((props, ref) => (
      <button ref=&#123;ref&#125; className="FancyButton">
        &#123;props.children&#125;
      </button>
    ));
    
    function App() &#123;
      const buttonRef = useRef(null);
    
      const handleClick = () => &#123;
        if (buttonRef.current) &#123;
          buttonRef.current.focus(); // 使用 ref 來聚焦按鈕
        &#125;
      &#125;;
    
      return (
        <div>
          <FancyButton ref=&#123;buttonRef&#125;>Click me!</FancyButton>
          <button onClick=&#123;handleClick&#125;>Focus Fancy Button</button>
        </div>
      );
    &#125;
    

    同場加映:useImperativeHandle

    目的是限制暴露的方法給父元件來做使用

    
    // 定義一個自定義輸入框組件,使用 forwardRef 傳遞 ref
    const CustomInput = forwardRef((props, ref) => &#123;
      const inputRef = useRef();
    
      // 使用 useImperativeHandle 來暴露 focus 方法給父組件
      useImperativeHandle(ref, () => (&#123;
        focus: () => &#123;
          inputRef.current.focus();
        &#125;
      &#125;));
    
      return <input ref=&#123;inputRef&#125; &#123;...props&#125; />;
    &#125;);
    
    function ParentComponent() &#123;
      const inputRef = useRef();
    
      const handleClick = () => &#123;
        inputRef.current.focus(); // 使用 ref 來聚焦輸入框
      &#125;;
    
      return (
        <div>
          <CustomInput ref=&#123;inputRef&#125; placeholder="Click the button to focus" />
          <button onClick=&#123;handleClick&#125;>Focus Input</button>
        </div>
      );
    &#125;
    

    說明:

    1. 自定義輸入框組件 CustomInput:使用 forwardRef 來接收 ref 並將其傳遞給內部的 input 元素。
    2. 使用 useImperativeHandle:這允許我們在父組件中自定義暴露的方法(如 focus)。
    3. 父組件 ParentComponent:使用 useRef 來創建 ref,並通過按鈕點擊觸發輸入框的聚焦。