React的一些高级用法(2)

536 阅读1分钟

React.forwardRef

在介绍这个api之前我们要知道为什么需要转发ref呢?因为不同于组件普通的props属性, 在父组件中设置的ref不会透传下去,而是像key一样,被React接收后进行了特殊的处理, 不会出现在子组件的props对象中。所以React.forwardRefreact的作用就是可以向子组件透传ref。

React.forwardRefreact官网的说明如下

L1VzZXJzL3poYW5nZnV5aW5nL0xpYnJhcnkvQXBwbGljYXRpb24gU3VwcG9ydC9EaW5nVGFsa01hYy8yODI1NDcxNjFfdjIvSW1hZ2VGaWxlcy8xNjU4OTk1NDg0MjM2XzVEMjE0OTdBLUIyNUUtNEY0MC04MDAwLTQzNzYwMTU4Qjc1MS5wbmc=.png

一句话概括就是React.forwardRef 可以在函数组件中转发ref

demo

import * as React from "react";

const Child = React.forwardRef((props, ref) => {
  return <input ref={ref} />;
});

const App: React.FC = () => {
  const ref = React.useRef();

  React.useEffect(() => {
    // ref.current保存的就是 input的dom
    console.log("ref", ref.current);
  }, []);

  return (
    <>
      <Child ref={ref} />
    </>
  );
};

export default App;

另外经常和React.forwardRef搭配使用还有一个useImperativeHandle hook。

下面是对useImperativeHandle的官网介绍

L1VzZXJzL3poYW5nZnV5aW5nL0xpYnJhcnkvQXBwbGljYXRpb24gU3VwcG9ydC9EaW5nVGFsa01hYy8yODI1NDcxNjFfdjIvSW1hZ2VGaWxlcy8xNjU5MDAxNTQ1NzE3X0YwNTA5QTRELTBBQTctNEVBNS04NTJDLUZERkIyREY3NzdENS5wbmc=.png

简单一句话总结就是: useImperativeHandle 可以把函数子组件本身的一些属性暴漏给父组件,作用类似与在类组件中父组件可以通过ref拿到子组件的实例

demo

import * as React from "react";

const Child = React.forwardRef((props, ref) => {
  const [count, setCount] = React.useState(0);

  React.useImperativeHandle(ref, () => {
    return {
      a: "a",
      setCount,
    };
  });

  return <div>{count}</div>;
});

const App: React.FC = () => {
  const ref = React.useRef();

  const handleClick = () => {
    if (ref.current) {
      console.log("ref.current", ref.current);

      ref.current.setCount((count) => count + 1);
    }
  };

  return (
    <>
      <Child ref={ref} />
      <button onClick={handleClick}>click</button>
    </>
  );
};

export default App;

L1VzZXJzL3poYW5nZnV5aW5nL0xpYnJhcnkvQXBwbGljYXRpb24gU3VwcG9ydC9EaW5nVGFsa01hYy8yODI1NDcxNjFfdjIvSW1hZ2VGaWxlcy8xNjU5MDAyMjY1MTg1XzA3QzFDNTAwLTM1RTUtNDU5My1CNkNGLUQ1Q0VFNURCODgyRC5wbmc=.png

上面的截图我们可以看到,在Child组件中通过useImperativeHandle 向父组件App暴漏了asetCount属性。在父组件就可以通过ref.current拿到这些子组件的属性。