Should I use ReactDOMServer.renderToString() or an

2019-07-28 22:24发布

问题:

I am extacting a tiny component from a bigger map component on an app using Leafet and it seems impossible to include the JSX into the html string of Leafet DivIcon.

bigger map component render part:

render () {
  const {tobject, strings} = this.props

  let circle = classes.redCircle

  if (tobject.lastPoint.activeEvents.ignition) {
    circle = classes.greenCircle
  }

  const icon = new window. L. DivIcon({
  html:
  ` <div class= ${classes.tobjecticon}><span class= ${classes.tobjecticontext}><div class= ${circle}></div></span></div> `
})

newly extacted component StatusCircle.js:

import React from 'react'
import classes from './StatusCircle.scss'

export const StatusCircle = ({ status}) => {

  let circle = classes.redCircle

  if (status) {
    circle = classes.greenCircle
  }

  return (
    <div className={circle} ></div>
  )
}

export default StatusCircle

My question seems similar to this one. I've tried renderToString() of StatusCircle, but using ReactDOM (deprecated there) and not ReactDOMServer and it didn't work saying there is no such function. Is it okay to use ReactDOMServer.renderToString() or .renderToStaticMarkup() to achieve this or is it better to leave unchanged without extraction?

回答1:

It is OK to leave inner html inside of parent component. But here is the way to render it to markup without using ReactDOMServer. It's a bit tricky way =)

class Inner extends React.Component {
  render () {
    return (
      <span {...this.props}>Inner Element</span>
    )
  }
}

class Outer extends React.Component {
  render () {    
    const span = document.createElement('span');
    ReactDOM.render(<Inner className="red" />, span);    
    
    //target html
    console.log(span.innerHTML);
    
    return (
      <div>
        You can use this html
        <pre>
          {span.innerHTML}
        </pre>    
      </div>
    )
  }
}

ReactDOM.render(<Outer />, document.querySelector('#root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>



回答2:

I don't want to add more imports to the project and depend on them, but using ReactDOM.Render instide render () is giving: "Warning: _renderNewRootComponent(): Render methods should be a pure function of props and state; triggering nested component updates from render is not allowed. If necessary, trigger nested updates in componentDidUpdate. Check the render method of StatusCircle". While ReactDOMServer.renderToStaticMarkup() works flawlessly like this:

class App extends React.Component{
  render() {

    let greenCircle = ReactDOMServer.renderToStaticMarkup(<StatusCircle status={true} />)
    console.log(greenCircle)
    let redCircle = ReactDOMServer.renderToStaticMarkup(<StatusCircle status={false} />)
    console.log(redCircle)

    return (
        <div>
          <StatusCircle status={true} />
          <StatusCircle status={false} />
        </div>
    )
  }
}

const StatusCircle = ({status}) => {

  let circle = "redCircle"

  if (status) {
    circle = "greenCircle"
  }

  return <div className={circle}></div>
}

ReactDOM.render(<App />, document.querySelector('#root'))

 
.redCircle {
  background-color: red;
  border-radius: 50px;
  width: 10px;
  height: 10px;
  margin: 10px;
}

.greenCircle {
  background-color: green;
  border-radius: 50px;
  width: 10px;
  height: 10px;
  margin: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom-server.min.js"></script>
<div id="root"></div>



标签: react-redux