簡體   English   中英

如何在 React 中將 Ref 傳遞給 SVG 組件

[英]How To Pass a Ref to a SVG Component in React

我有一個 svg 組件,聲明如下:


import {ReactComponent as Icon} from 'someplace.svg'

function SomeComponent(props){
   const [someState, setSomeState] = useState(0)
   const iconRef = useRef(null)

   useEffect(() => {
      //always prints null
      console.log(iconRef.current) 
   }, [someState])

return <div>
 <button onClick={() => setSomeState(prev => prev + 1)}>{someState}</button>
 <Icon ref={iconRef}/>
</div>
}

這里的問題是 iconRef 將始終返回 null。我認為這是因為它被聲明為一個組件,因此需要將 ref 直接轉發到 svg 標簽,但我該怎么做呢?

有任何想法嗎?

我不確定這是否適用於create-react-app ,但無論如何它已經死了。

首先你需要安裝svgr

npm i @svgr/webpack

添加一個svgr配置文件。

./.svgrrc.js

module.exports = {
  ref: true,
}

和 webpack 配置。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.svg$/i,
        use: ['@svgr/webpack'],
      },
    ],
  },
}

如果使用next ,請在next.config.js中插入 webpack 配置。

const webpack = require('webpack');

module.exports = {
  webpack(config) {
    config.module.rules.push({
      test: /\.svg$/,
      use: ['@svgr/webpack'],
    });
    return config;
  },
};

然后你可以這樣做:

import Icon from "@icons/icon.svg";

const IconWithRef () => {
  const ref = useRef<SVGSVGElement | null>(null);

  return (
      <Icon width="50" ref={ref} />
  );
};

您可以檢查此沙箱以獲取工作版本。

更新

使用它,我在將 svg 路徑直接用於.css文件時遇到了一些問題,因為 webpack 將其解析為反應組件。 我可以找到使兩者都起作用的解決方法是像這樣更改webpack設置。

module.exports = {
  module: {
    rules: [
      {
        test: /\.svg$/i,
        type: 'asset',
        resourceQuery: /url/,
      },
      {
        test: /\.svg$/i,
        resourceQuery: { not: [/url/] },
        use: ['@svgr/webpack'],
      },
    ],
  },
}

然后在.css中使用svg的路徑,例如:

.svg-background {
  background-image: url('../path/to/svg/image.svg?url');
}

注意末尾的?url查詢參數。

使用選項issuer: /\.[jt]sx?$/ ,就像在文檔中一樣,對我不起作用。

這可以通過 3 個步驟解決:

  1. 獲取 SVG 圖標作為代碼庫中的 React 組件。
  2. setRef傳遞給它。

例子:

將 SVG 代碼抓取到組件中,如下所示:

const CloseIcon = (props) => (
  <svg
    width="38"
    height="38"
    viewBox="0 0 38 38"
    fill="none"
    xmlns="http://www.w3.org/2000/svg"
  >
    <circle cx="19" cy="19" r="18" stroke="#AFAFAF" stroke-width="2"></circle>
    <path
      d="M13.0548 13.336L24.9868 25.9185"
      stroke="#AFAFAF"
      stroke-width="2"
      stroke-linecap="round"
      stroke-linejoin="round"
    ></path>
    <path
      d="M24.9862 13.3365L13.0542 25.9189"
      stroke="#AFAFAF"
      stroke-width="2"
      stroke-linecap="round"
      stroke-linejoin="round"
    ></path>
  </svg>
)

export default CloseIcon

然后,在使用此圖標的父組件中,設置其 ref 屬性,例如:


...

const closeIconRef = createRef()
...

<CloseIcon
   style={{ position: 'absolute', top: 18, right: 18, cursor: 'pointer' }} 
   setRef={closeIconRef}
/>

然后將setRef添加到 SVG 組件中的標簽:

const CloseIcon = ({ setRef }) => (
  <svg
    ref={setRef}
    width="38"
    height="38"
    viewBox="0 0 38 38"
    fill="none"
    xmlns="http://www.w3.org/2000/svg"
  >
...

你完成了!

*要記住的重要一點:子節點仍然是非引用的,所以如果在命中的路上沒有形狀,它就可以工作。 您可以為每個孩子附加一個參考。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM