Lee Soon Fatt
Lee Soon Fatt

Reputation: 177

React.js data won't load at the first time only after refresh it works

Currently, I build a website in react.js and a problem came up. I think that when I click on a page that requires a script, the first time I enter the scripts does not work. but after when I refresh the page. suddenly the data appear. I think that my JavaScripts is no loading it, but if I refresh the page and it starts working

import React from 'react';
import "./Information.css";


function Information({imgStart,img, alt, name, age, gender,bio,qualification_acedemic,institution_acedemic,organisation,role,year,level,role_admin,level_admin,start_admin,end_admin
,area_expertise,book_pub,chp_book_pub,title_Areas,role_Areas,title_consult,role_consult,organisation_consult,fromTo_consult
,award,institution_award,year_award,activity_contribute,fromTo_contribute,role_contribute,name_degree,name_candidates,title_thesis,academic_level,academic_teach,course_teach,hourContact_teach,number_student_teach}) {

   
    return (
     
        <>
        <div className="container_details">
            <div className="row_details"
                style={{display: "flex", flexDirection: imgStart === 'start' ? "row-reverse" : "row" }}> 
                <div className="col-personal-logo"> 
                    <img src={img} alt={alt} className="personal-image"/>
                    <h2>{name}</h2>
                    <p>Age:{age}</p>
                    <p>Gender:{gender}</p>
                    <p></p>
                </div>  
                <div className="col-personal">
                    <button class="accordion">Biography</button>
                    <div class="panel">
                    
                    <p>{bio}</p>
                    </div>

                    <button class="accordion">Academic Qualification</button>
                    <div class="panel">
                    <p>Qualification: {qualification_acedemic}</p>
                    <p>Institution: {institution_acedemic}</p>
                    </div>

                    <button class="accordion">Professional</button>
                    <div class="panel">
                    <p>Organisation: {organisation}</p>
                    <p>Role: {role}</p>
                    <p>Year: {year}</p>
                    <p>Level: {level}</p>
                    </div>

                    
                </div>
                

            </div>

        </div>
     
            
        </>

        
    )
}

    


export default Information

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta
      name="description"
      content="Web site created using create-react-app"
    />
    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
    <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.15.0/css/all.css"
     integrity="sha384-OLYO0LymqQ+uHXELyx93kblK5YIS3B2ZfLGBmsJaUyor7CpMTBsahDHByqSuWW+q" crossorigin="anonymous">
   
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
  
    <title>UOW Portal</title>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
   
    
  </body>
  <script>
    var acc = document.getElementsByClassName("accordion");
    var i;

    
        for (i = 0; i < acc.length; i++) {
        acc[i].addEventListener("click", function() {
            /* Toggle between adding and removing the "active" class,
            to highlight the button that controls the panel */
            this.classList.toggle("active");

            /* Toggle between hiding and showing the active panel */
            var panel = this.nextElementSibling;
            if (panel.style.display === "block") {
            panel.style.display = "none";
            } else {
            panel.style.display = "block";
            }
        });
        }

  </script>
</html>

app.js

import React from 'react';
import "./App.css"
import Navbar from './components/Navbar';
import { Switch, Route} from 'react-router';
import { BrowserRouter } from 'react-router-dom'
import Home from './components/pages/HomePage/Home'
import Footer from './components/pages/Footer/Footer';
import Service from './components/Service';

import Info from './components/pages/Info/Info';
import infoMs from './components/pages/Info/infoMs';



function App(){
  return(
    <BrowserRouter>
      <Navbar />
      <Switch>
        <Route path='/' exact component={Home}/>
        <Route path='/service' exact component={Service}/>
        <Route path='/phua' component={Info}/>
        <Route path='/foong' component={infoMs}/>

      </Switch>
      
      <Footer />
    </BrowserRouter>
  );
}

 

export default App;

Upvotes: 1

Views: 3967

Answers (1)

Asad S
Asad S

Reputation: 2116

I don't think that's the way React meant to works!

REASON

React uses what known as Client-Side Rendering, so things like getting an element using getElementById or getElementByClassName shouldn't work. Because, (CMIIW) the rendering of the elements is not finished yet when your getElementById scripts already running, so that it cannot find the elements.

SOLUTION

However, if you want to make your view respond to click event, you can put your function on the component. Meaning, instead creating an event listener using addEventListener, you should do:
<button class="accordion" onClick={/*YOUR CLICK LISTENER HERE*/}>Biography</button>

not only that, you should create a state of open/close by using a React State (either hooks or component based state). And your click handler should toggle the state true or false.

However, as words are hard to digest 🥴, let me show a code example 😄. Create a new component Accordion, like this:

function Accordion({ children, title }) {
    const [show, setShow] = useState(false)

    const toggle = () => setShow(state => !state)

    return (
      <div>
        <button class="accordion" onClick={toggle}>{title}</button>
        {show && 
          <div class="panel">
            {children}
          </div>
        }
      </div>
    )
}

Then use it like this:

function Information(....) {
  ......

  <Accordion>
    <div>
      <p>Qualification: {qualification_acedemic}</p>
      <p>Institution: {institution_acedemic}</p>
    </div>
  </Accordion>

  ......
} 

This Accordion component should have the ability to open and close independently. If you want to make it dependent of the other, you can implement more advanced state or use a third party component, maybe this component.

CONCLUSION

I think you should use the React way of making your UI responsive and not trying the vanilla way which actually are like fighting with React.

Upvotes: 1

Related Questions