cgobbet
cgobbet

Reputation: 319

Switch to different component after button click with React

I am absolutely new to React and need to create a button to take the user from a current component (MovieView) to the main one (MainView). I managed to create it properly and I used onClick to trigger the display of MainView. I know I cannot call a class from a function (so as console says), so I created a second function to be called and trigger MainView. But as you may wonder, it does not work. This is the code I am using:

import React from 'react';
import { MainView } from '../main-view/main-view';

function NewButton() {
  return <MainView />;
}

export class MovieView extends React.Component {

  constructor() {
    super();

    this.state = {};
  }

  render() {
    const { movie } = this.props;

    if (!movie) return null;

    return (
      <div className="movie-view">
        <img className="movie-poster" src={movie.imagePath} />
        <div className="movie-title">
          <span className="label">Title: </span>
          <span className="value">{movie.title}</span>
        </div>
        <div className="movie-description">
          <span className="label">Description: </span>
          <span className="value">{movie.plot}</span>
        </div>

        <div className="movie-genre">
          <span className="label">Genre: </span>
          <span className="value">{movie.genre.name}</span>
        </div>
        <div className="movie-director">
          <span className="label">Director: </span>
          <span className="value">{movie.director.name}</span>
        </div>
        <div className="back-movies">
          <button onClick={NewButton}>Back</button>
        </div>
      </div>
    );
  }
}

Could you any seeing this to point the path to take or how I can call this MainView class properly. I understand it's a simple task, but I am afraid I still haven't absorbed React principles yet. Thanks in advance to you all.

Upvotes: 0

Views: 1791

Answers (4)

cgobbet
cgobbet

Reputation: 319

I reached a solution that I'd not do with the help I had here. I have first pasted here some pieces of code but, I believe it can be helpful to give the whole answer.

So, the question I placed here was regarding a component called <MovieView, that was a part of an app that interacted with another component (in another file) called MainView.

The solution was the insertion of the method onClick on the live 14 of <MovieView> and the button on line 39 that you can see at this file on Github. If the file was updated, check the version for November 22nd.

The solution had, however, been found in the main component, <MainView>, adding code on lines 48 and 49. Here is the link to the file: https://github.com/cgobbet/react-client/blob/master/src/components/main-view/main-view.jsx

The repository with the whole app is on this page: https://github.com/cgobbet/react-client.

And sorry for the reviewers (I had accidentally deleted part of the fantastic answer submitted by @nick-miller.

Upvotes: 0

Shyam
Shyam

Reputation: 5497

If you need to add or remove components or show a new view based on an user action in react we need to do this via state .

import React from 'react';
import { MainView } from '../main-view/main-view';

export class MovieView extends React.Component {

constructor() {
super();

this.state = {
  showMainView: false;
};
}

toggleMainView = () => this.setState(prevState => ({ showMainView: 
!prevState.showMainView})) 

render() {
const { movie } = this.props;
const { showMainView } = this.state;
if (!movie) return null;

return (
  <div className="movie-view">
    <img className="movie-poster" src={movie.imagePath} />
    <div className="movie-title">
      <span className="label">Title: </span>
      <span className="value">{movie.title}</span>
    </div>
    <div className="movie-description">
      <span className="label">Description: </span>
      <span className="value">{movie.plot}</span>
    </div>

    <div className="movie-genre">
      <span className="label">Genre: </span>
      <span className="value">{movie.genre.name}</span>
    </div>
    <div className="movie-director">
      <span className="label">Director: </span>
      <span className="value">{movie.director.name}</span>
    </div>
    <div className="back-movies">
      <button onClick={this.toggleMainView}>Back</button>
    </div>
    // render the mainView based on the state
    { showMainView && <MainView />}
  </div>
);
}
}

Upvotes: 0

Hannibal B. Moulvad
Hannibal B. Moulvad

Reputation: 131

I make the Class into a Function Component instead, and implement it like this :-)

import React from "react";
import { MainView } from '../main-view/main-view';

export const MovieView = ({ movie }) => {
    const { showMainView, setShowMainView } = React.useState(false);

    if (!!movie) {
        return null;
    }

    function toggleMainView() {
        setShowMainView(true);
    }

    return (
        <React.Fragment>
            { showMainView ? (
                <MainView />
            ) : (
                <div className="movie-view">
                    <img className="movie-poster" src={movie.imagePath} />
                    <div className="movie-title">
                        <span className="label">Title: </span>
                        <span className="value">{movie.title}</span>
                    </div>
                    <div className="movie-description">
                        <span className="label">Description: </span>
                        <span className="value">{movie.plot}</span>
                    </div>

                    <div className="movie-genre">
                        <span className="label">Genre: </span>
                        <span className="value">{movie.genre.name}</span>
                    </div>
                    <div className="movie-director">
                        <span className="label">Director: </span>
                        <span className="value">{movie.director.name}</span>
                    </div>
                    <div className="back-movies">
                        <button onClick={() => toggleMainView()}>Back</button>
                    </div>
                </div>
            )}
        </React.Fragment>
    );
};
export default MovieView;

Upvotes: 0

Nick Muller
Nick Muller

Reputation: 2283

Without introducing additional dependencies, probably the easiest way for this example is to use state to track if the button has been clicked. If it has been clicked, render MovieView, if not render MainView.

For this you need to following:

  • Set state variable that tracks that MainView should be rendered in onClick event. (boolean will probably suffice)
  • in render():
    • if the state var is false, render the content of MovieView.
    • if the state var is true, render the MainView component.

Implementation details are left as an exercise :)

If you're using a router already (like react-router) you could probably just update the url to an url that is linked to the MainView component..

Upvotes: 1

Related Questions