如何修改导入的第三方反应组件的tagName?

时间:2017-04-22 01:04:16

标签: javascript reactjs svg babeljs

我正在使用babel-plugin-inline-react-svg导入SVG并将其用作反应组件。问题是我需要将这些SVG嵌入到另一个SVG中。我想将根标记svg转换为symbol。当我按原样导入SVG时,结果是嵌套的SVG标记。这在技术上有效,但并非没有很多针对我的目标实现的怪癖(phantomjs)。我宁愿使用use xlink:href,但我需要将第三方lib生成的根元素转换为标记名称符号

这是一些虚构的用法

import Flag from 'images/icons/flag.svg'

export default () => {
  return (
     <svg>
       <Flag/>
       <text>Foo</text>
     </svg>
   )
}

这呈现的是

<svg>
    <svg>
      <!-- contents of svg -->
    </svg>
    <text>Foo</text>
</svg>

我希望能够做的是

import Flag from 'images/icons/flag.svg'

export default () => {
  return (
     <svg>
       <defs>
          <Flag as="symbol" id="flag"/>
       </defs>
       <use xlinkHref="#flag"/>
       <text>Foo</text>
     </svg>
   )
}

必须更改第三方库的根元素的tagName才是一个非常常见的用例。如果没有,只是添加咏叹调标签,使用语义元素名称等等。

如何更改无法控制的反应组件的tagName?

1 个答案:

答案 0 :(得分:0)

I ended up using a Higher Order Component to intercept the ReactDOMElement coming from the 3rd party lib. I switched the type of the element before it renders. Inspired heavily by https://github.com/pwmckenna/react-transform-style/blob/master/src/index.js

const TransformTag = (Component, tagName) => {
  const ModifiedComponent = Component
  const isFn = (typeof(Component) === 'function')
  const render = isFn ? ModifiedComponent : ModifiedComponent.render
  const modifiedRender = function() {
    const {
      props,
      ...renderedRest
    } = render.apply(this, arguments)

    renderedRest.type = tagName // this is the magic
    return {
      props,
      ...renderedRest
    }
  }
  if (isFn) {
    return modifiedRender
  } else {
    ModifiedComponent.prototype.render = modifiedRender
    return ModifiedComponent
  }
}

// usage 

export default SvgQuote = () => { 
   return (
      <svg>
         <defs> 
            { TransformTag(Bill, 'symbol') }
         </defs>
      </svg>
   )
}