How to render a component using innerHTML in React jsx

10,998

Solution 1

You can not create React components by putting them into strings, using JSX, your code can be shortened to the following :

this.state.showGraph ? <span>Graph View!</span> : <ShotLog shotLog={this.state.shotLog} />

Using a ternary condition, you can decide what to render depending on the value of a variable, showGraph

showGraph will be stored in your component's state, accessible via this.state, when you want to change the value of something in your state, you will have to call setState, this will cause your component to rerender everything on your screen and show you what you want

Working example :

class ShotLog extends React.Component {
  render() {
    return <div>Hi I'm a ShotLog</div>
  }
}


class App extends React.Component {
  constructor(props){
    super(props)
    this.state = { showGraph: true }
  }
  handleClick = ev => {
    this.setState({ showGraph: !this.state.showGraph })
  }
  render() {
    return (
      <div>
        {this.state.showGraph ? 
          <span>Graph View!</span> 
          : 
          <ShotLog />}
        <button onClick={this.handleClick}>Switch me !</button>
      </div>
    )
  }
}
    
ReactDOM.render(
  <App/>,
  document.getElementById('react')
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.0.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.0.0/umd/react-dom.production.min.js"></script>
<div id="react"></div>

You will find the basics of JSX on the following official documentation : https://reactjs.org/docs/introducing-jsx.html

And you can learn more here about the state of your components : https://reactjs.org/docs/state-and-lifecycle.html

Solution 2

I am not expert of ReactJS, but I think you should return proper content instead of trying to change it via JS:

  toggleView() {
      if (this.isGraphView()) {
          return <span>Graph View!</span>;
      } else {
          return <ShotLog shotLog={this.state.shotLog}/>
      }
  }

Solution 3

In conjunction with @Justinas's answer, you can try doing a conditional render instead of doing it with pure JS. You can try something like this:

MyComponent extends React.Component {
  constructor(props) {
      super(props);
      this.state = {currView: 'graph'};
  }

  handleToggle() {
      if (this.state.currView === 'graph') {
          this.setState({currView: 'otherView'});
      } else {
          this.setState({currView: 'graph'});
      }
  }

  render() {
      if(this.state.currView === 'graph') {
          // render your 'graph' view
      } else {
          // render some other view
      }
   }
}

A change to the component's state will cause a re-render so it should completely change whatever was previously there. Just make sure you have something that can toggle or update the state :)

P.S. Sorry if I made some mistakes in the react related syntax. No IDE right now lol

Solution 4

Instead of trying to access the dom directly using document.getElementsByClassName, you can use react way to toggle the view. You can take reference to my example below.

class TestComponent 
{

constructor(props) {
  super(props); 
  this.state = {
    view: 'list', 
    shotLog: someVal
  }

  handleToggle() {
     const modifiedView= this.state.view == 'graph'? 'list': 'graph'; 
     this.setState(() => {
      return {view: modifiedView}; 
     });

  }

}


render() {
     const {view, shotLog} = this.state;
     <div> 
       <button onClick={this.handleToggle}> Toggle </button> 

       {view == 'graph'} && <span> Graph View! </span> 
       {view == 'list'} && <ShotLog shotLog={shotLog} /> 


     </div>
}



}
Share:
10,998

Related videos on Youtube

oolongloop
Author by

oolongloop

Updated on July 16, 2022

Comments

  • oolongloop
    oolongloop almost 2 years

    I'm currently writing functionality that will toggle between two views, graph and list. two is the name of the class of the view's container.

      toggleGraphView() {
        const two = document.getElementsByClassName('two')[0];
        two.innerHTML = '<span>Graph View!</span>'
      }
    
      toggleListView() {
        const two = document.getElementsByClassName('two')[0];
        two.innerHTML = "<ShotLog shotLog={this.state.shotLog}/>"
      }

    The component switches to the graph view text just fine ('Graph View!') but when I try to switch back to list view, I get nothing. After firing toggleListView, in chrome tools the two container contains <shotlog shotlog="{this.state.shotLog}/"></shotlog>. I need it to look like <ShotLog shotLog={this.state.shotLog}/> in order to pass props correctly.

    I'm not sure where the extra quotations are coming from. Any ideas?

  • oolongloop
    oolongloop over 5 years
    Thanks so much! This is exactly what I needed help with. Cheers
  • Treycos
    Treycos over 5 years
    Glad I could help :)