Melvin Jensen
Melvin Jensen

Reputation: 39

Trying to dynamically select components in React

I'm super new to React and I have two components I want to toggle between based on a user click. I've went about it by creating a 'currentView' state and using that to set/update what the user should be looking at, but when I try to get the components to display it throws tag errors. Here's my code:

class App extends Component {
  constructor(props){
    super(props);

    this.state={
      currentView: "Welcome",
    };
  }

  goTrack() {
    this.setState({currentView: "Tracker"});
    console.log(this.state.currentView);
  }

  goReview() {
    this.setState({currentView: "Review"});
    console.log(this.state.currentView);
  }

  render() {
    return (
      <div className="App">
        <aside>
          <nav>
            <ul>
              <li onClick={()=>this.goTrack()}> Tracker </li>
              <li onClick={()=>this.goReview()}> Review </li> 
            </ul>
          </nav>
        </aside>
        <main>  
         <this.state.currentView/>
        </main>
      </div>
    );
  }
}

export default App;

My question is how should I go about dynamically selecting components to display without re-rendering the entire DOM?

Upvotes: 3

Views: 3343

Answers (3)

J.Lindebro
J.Lindebro

Reputation: 223

One way to solve this is to use the current state to match a key in an object containing the component you want in a certain state.

constructor() {
  super()
  this.state = {
    current: 'welcome',
  }
}


render() {
  const myComponents = {
    welcome: <Welcome />,
    tracker: <Tracker />,
  }
  const CurrentComponent = myComponents[this.state.current]

  return (
    <CurrentComponent />
  )
}

And when you change the state current with the value 'tracker', Tracker component will be rendered instead of Welcome component.

Upvotes: 3

L&#233;opold Houdin
L&#233;opold Houdin

Reputation: 1525

Option 1: Conditions

render() {
  const { currentView } = this.state;

  // I omit the other stuff to focus on your question
  return (
    <div>
      {currentView === 'Welcome' && <Welcome />}
      {currentView === 'Tracker' && <Tracker />}
      {currentView === 'Review' && <Review />}
    </div>
  );
}

Option 2: Dynamic component

import Welcome from './Welcome';
import Review from './Review';

class App extends Component {
  constructor(props) {
    super(props);

    this.state = {
      current: Welcome,
    };
  }

  // ... stuff ...

  goTrack() {
    this.setState(prevState => { ...prevState, current: Review });
  }

  // ... other stuff ...

  render() {
    # I rename it because React expects a component's name
    # with a capital name.
    const { current: Current } = this.state;

    # As above, I put only relevant rendering
    return <div><Current /></div>;
  }
}

Option 3: Guess

And actually, looking at what you are trying to do, I'd suggest you have a look at react-router-dom.

Upvotes: 0

Moniruzzaman Monir
Moniruzzaman Monir

Reputation: 121

I am guessing Tracker and Review are two components you want to toggle based on value in this.state.currentView

In short this <this.state.currentView/> expects a component/html element.

one way to do what you want to do would be to do this instead.

<main> 
   { this.state.currentView == 'Review' && (
      <Review />
   )}
   { this.state.currentView == 'Tracker' && (
       <Tracker />
   )}
</main>

Upvotes: 0

Related Questions