user18673335
user18673335

Reputation:

Possible to swap react components out via onClick's?

I have questions similar to this on my profile, but now am aiming to be specific, below I have code that populates an html file, using routes to "switch pages" or components, labeled as Apps. The main component I am trying to alter is App2, which contains a grid of exercises, and has repeating divs with their own id's to filter out exercises. However, on div click, I want to populate the root div with a grid (into the component value) component that represents the div you click. For example, clicking Gym div only shows gym exercises, etc. My grids all the right exercises to display, It is just a matter of swapping the default one out (component) with the filtered ones.

import { render } from "react-dom";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import App1 from "./App1";
import App2 from "./App2";
import App3 from "./App3";

const rootElement = document.getElementById("page");
render(
  <BrowserRouter>
    <Routes>
      <Route path="/" element={<App1 />} />
      <Route path="Exercises" element={<App2 />} />
      <Route path="Scheduler" element={<App3 />} />
    </Routes>
  </BrowserRouter>,
  rootElement
);

import React from "react";
import NavBar from "./components/NavBar";
import Grid from "./components/Exercises/Grid";
import GridCardio from "./components/Exercises/GridCardio";
import GridHome from "./components/Exercises/GridHome";
import GridGym from "./components/Exercises/GridGym";
import GridUpper from "./components/Exercises/GridUpper";
import GridLower from "./components/Exercises/GridLower";

function App2(){
  let component = <Grid/>;
  function applyHome(){
    //also applyUpper/Gym/Home/...
    component = <GridHome/>
  }
 return( 
              <div id="Home/Upper/Cardio/Gym" class="col-lg-6 d-flex align-items-stretch">
                <div style={cursorPointer} onClick={applyHome/Gym/Upper/Cardio...}  class="card w-100 mb-4 rounded-3 shadow-sm filter">
                  <div class="card-heading py-1">
                    <h1 class="normal-heading">At Home</h1>
                  </div>
                  <div class="card-body">
                    <p>
                      Small, mobile, or convenient equipment that still has use.
                    </p>
                  </div>
                </div>
              </div>
       <section>
        <div class="album py-5 black-section">
          <div id="root" class="container">
            {/* THIS WILL CHANGE BASED ON CLICKS */}
            {component}
          </div>
        </div>
      </section>
              );
              }
How the app works, showing off exercise identifiers (home, gym, body group)

I know clicking the div's work, as I used an alert prior to see if the server would respond to clicks, however, the component does not change, and the original (or component value) stays the same.

Upvotes: 1

Views: 642

Answers (2)

user18673335
user18673335

Reputation:

I actually came up with an answer that was a lot easier than I anticipated. All I did was use a hook! On click, these functions are called and everything works as intended.

import React, { useState } from 'react';

import {render} from 'react-dom';
import NavBar from "./components/NavBar";
import Grid from "./components/Exercises/Grid";
import GridCardio from "./components/Exercises/GridCardio";
import GridHome from "./components/Exercises/GridHome";
import GridGym from "./components/Exercises/GridGym";
import GridUpper from "./components/Exercises/GridUpper";
import GridLower from "./components/Exercises/GridLower";

const marginAuto = {
  margin: "auto"
};
const cursorPointer = {
  cursor: "pointer"
};

//THIS IS ALL RESPONSIBLE FOR LOADING EVERYTHING IN ONE PAGE DONT WORRY ABOUT IT
function App2() {
  // const [display, setState] = React.useState(<Grid/>);
  let component = <Grid/>;
  const [gridState, changePlease] = useState(component);

  function applyHome(){
    changePlease(<GridHome/>);
  }
  function applyCardio(){
    changePlease(<GridCardio/>);
  }
  function applyLower(){
    changePlease(<GridLower/>);
  }
  function applyUpper(){
    changePlease(<GridUpper/>);
  }
  function applyHome(){
    changePlease(<GridHome/>);
  }
  function applyGym(){
    changePlease(<GridGym/>);
  }

  return (<section>
    <NavBar/>

    <main>
      <section class="colored-section" id="title">
        <div class="container-fluid">
          <div class="row">
            <div class="container-fluid main-text">
              <h1 class="big-heading">Exercises</h1>
              <p>
                Below, feel free to navigate to whatever execrises you may find useful for your next workout. Either learn more about the exercise, or add it to your catelog to later add to your scheduler.
              </p>
            </div>
          </div>

          <h2 class="normal-heading mb-4">Group</h2>
          <div class="container-fluid row row-cols-1 row-cols-md-3 mb-3 text-center" style={marginAuto}>
            <div id="Gym" class="col-lg-6 d-flex align-items-stretch">
              <div style={cursorPointer} onClick={applyGym} class="card w-100 mb-4 rounded-3 shadow-sm filter">
                <div class="card-heading py-1">
                  <h1 class="normal-heading">Gym</h1>
                </div>
                <div class="card-body">
                  <p>You have equipment that is found at an ordinary gym.</p>
                </div>
              </div>
            </div>

              <div id="Home" class="col-lg-6 d-flex align-items-stretch">
                <div style={cursorPointer} onClick={applyHome}  class="card w-100 mb-4 rounded-3 shadow-sm filter">
                  <div class="card-heading py-1">
                    <h1 class="normal-heading">At Home</h1>
                  </div>
                  <div class="card-body">
                    <p>
                      Small, mobile, or convenient equipment that still has use.
                    </p>
                  </div>
                </div>
              </div>

          </div>

          <h2 class="normal-heading mb-4">Equipment</h2>
          <div class="container-fluid row row-cols-1 row-cols-md-3 mb-3 text-center" style={marginAuto}>

            <div id="Upper" class="col-lg-4 d-flex align-items-stretch">
              <div style={cursorPointer} onClick={applyUpper}  class="card w-100 mb-4 rounded-3 shadow-sm filter">
                <div class="card-body">
                  <h1 class="normal-heading">Upper Body</h1>
                  <p>
                    Includes the chest, arms, shoulders, and anything else above the waist.
                  </p>
                </div>
              </div>
            </div>

            <div id="Lower" class="col-lg-4 d-flex align-items-stretch">
              <div style={cursorPointer} onClick={applyLower} class="card w-100 mb-4 rounded-3 shadow-sm filter">
                <div class="card-body">
                  <h1 class="normal-heading">Lower Body</h1>
                  <p>
                    Includes the quadriceps, hamstrings, glutes, and anything else below the waist.
                  </p>
                </div>
              </div>
            </div>

            <div id="Cardio" onClick={applyCardio} class="col-lg-4 d-flex align-items-stretch">
              <div style={cursorPointer}  class="card w-100 mb-4 rounded-3 shadow-sm filter">
                <div class="card-body">
                  <h1 class="normal-heading">Cardio</h1>
                  <p>
                    Any exercise that benefits the cardio-system that gets the heart pumpin.
                  </p>
                </div>
              </div>
            </div>

          </div>
        </div>
      </section>

      <section>
        <div class="album py-5 black-section">
          <div id="root" class="container">
            {/* THIS WILL CHANGE BASED ON CLICKS */}
             {gridState}
          </div>
        </div>
      </section>

      <footer id="footer">
        <div class="container-fluid">
          <a href="index.html">
            {" "}
            <img class="logo mb-3" src="https://raw.githubusercontent.com/fabianenavarro/Get-a-Grip/main/public/images/fist.png" alt=""/>
          </a>
          <p>2022 Getta Grip! LLC</p>
        </div>
      </footer>

    </main>);
  </section>);
}

export default App2;

Upvotes: 1

Domino987
Domino987

Reputation: 8774

You need to rerender after the click by saving the current component. Just changing the variable value does not trigger a rerender because jsx doe snot actually render anything but creates objects that react will display on render. And save the current selection in a state.

Try this:

function App2(){
const [display, setDisplay] = React.useState("grid");

let component = <Grid/>;
switch(display) {
    case "home":
       component = <GridHome/>
       break;
    // Fill in the rest
}
function applyHome(){
    setDisplay("home") // or other tags that you want to check with the switch
}

Upvotes: 0

Related Questions