How to render a component using innerHTML in React jsx
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>
}
}
Related videos on Youtube
oolongloop
Updated on July 16, 2022Comments
-
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 over 5 yearsThanks so much! This is exactly what I needed help with. Cheers
-
Treycos over 5 yearsGlad I could help :)