skip to Main Content

Please Some Help!

My project has 4 page that one of them is About.
I use react-router for change path and contents between this pages with their link

import React from 'react';
import { BrowserRouter as Router, Switch, Route, Link } from "react-router-dom";
import './App.css';
import "./js/script";
import Home from "./components/Home";
import About from "./components/About";
import Contact from "./components/Contact";
import Portfolio from "./components/Portfolio";

export default class App extends React.Component {
  render() {
    return(
      <Router>
        <div id="main-container-ma2web">
          <nav id="main-menu-ma2web">
            <ul>
              <li>
                <Link to='/' className="menu-link-ma2web">Home</Link>
              </li>
              <li>
                <Link to='/portfolio' className="menu-link-ma2web">Portfolio</Link>
              </li>
              <li>
                <Link to='/about' className="menu-link-ma2web">About</Link>
              </li>
              <li>
                <Link to='/contact' className="menu-link-ma2web">Contact</Link>
              </li>
            </ul>
          </nav>

          <Switch>
            <Route path='/about'>
              <About />
            </Route>
            <Route path='/contact'>
              <Contact />
            </Route>
            <Route path='/portfolio'>
              <Portfolio />
            </Route>
            <Route path='/'>
              <Home />
            </Route>
          </Switch>
        </div>
      </Router>
    );
  }
}

In About component I use some JavaScript code for some objects in it.

I attach my external JavaScript codes to project with different way such as script tag in index.html, functions, import, componentDidMount an so on…

If I be in About page http://localhost:3000/about and reload the page my JavaScript code works well but if I change path and return to About, JavaScript code does not works!

what should I do?

About.js

import React from 'react';

export default class About extends React.Component {
    componentDidMount() {
        document.title = 'About MA2WEB - Full-Stack Web Developer';
    }
    render() {
        return (
            <section className="main-section about animate">
                <article className="about-contents-ma2web">
                    <h1 className="typing-ma2web">I have experience in <span
                    className="txt-rotate"
                    data-period="2000"
                    data-rotate='[ "JavaScript", "Reactjs", "Nodejs", "GSAP", "PHP", "MySQL", "Wordpress", "SEO" ]'>
                        </span>
                    </h1>
                    <p>
                        I can develop both client and server side languages.
                    </p>
                </article>
            </section>
        );
    }
}

script.js

var TxtRotate = function(el, toRotate, period) {
  this.toRotate = toRotate;
  this.el = el;
  this.loopNum = 0;
  this.period = parseInt(period, 10) || 2000;
  this.txt = '';
  this.tick();
  this.isDeleting = false;
};

TxtRotate.prototype.tick = function() {
  var i = this.loopNum % this.toRotate.length;
  var fullTxt = this.toRotate[i];

  if (this.isDeleting) {
    this.txt = fullTxt.substring(0, this.txt.length - 1);
  } else {
    this.txt = fullTxt.substring(0, this.txt.length + 1);
  }

  this.el.innerHTML = '<span class="wrap">'+this.txt+'</span>';

  var that = this;
  var delta = 300 - Math.random() * 100;

  if (this.isDeleting) { delta /= 2; }

  if (!this.isDeleting && this.txt === fullTxt) {
    delta = this.period;
    this.isDeleting = true;
  } else if (this.isDeleting && this.txt === '') {
    this.isDeleting = false;
    this.loopNum++;
    delta = 500;
  }

  setTimeout(function() {
    that.tick();
  }, delta);
};

window.onload = function() {
  var elements = document.getElementsByClassName('txt-rotate');
  for (var i=0; i<elements.length; i++) {
    var toRotate = elements[i].getAttribute('data-rotate');
    var period = elements[i].getAttribute('data-period');
    if (toRotate) {
      new TxtRotate(elements[i], JSON.parse(toRotate), period);
    }
  }
};

4

Answers


  1. I think you should try importing your external js file in the “index.js” file.

    Login or Signup to reply.
  2. Try using BrowserRouter instead of Router.

    You can rename the import by using import {BrowserRouter as Router, Switch, Route} from 'react-router'

    Login or Signup to reply.
  3. The reason this is happening is because react-router loads index.html once. Any redirecting after that only repaints the DOM and doesn’t rerun any code in script tags. The only way to rerun script tags is to reload the page (which you’ve figured out).

    One suggestion is append the script tag whenever your component mounts. Don’t forget to cleanup after yourself.

    export default class About extends React.Component {
    
      componentDidMount() {
        document.title = 'About MA2WEB - Full-Stack Web Developer';
    
        const script = document.createElement('script');
        script.id = "myScript";
        script.text = "alert('hello')";
        document.body.appendChild(script);
      }
    
      componentWillUnmount() {
        const script = document.getElementById("myScript");
        script.parentNode.removeChild(script);
      }
    
      render() {
        return (
          <section className="main-section about animate">
            <article className="about-contents-ma2web">
              <h1 className="typing-ma2web">I have experience in
                <span className="txt-rotate"
                  data-period="2000"
                  data-rotate='[ "JavaScript", "Reactjs", "Nodejs", "GSAP", "PHP", "MySQL", "Wordpress", "SEO" ]'>
                </span>
              </h1>
              <p>
                I can develop both client and server side languages.
              </p>
            </article>
          </section>
        );
    
      }
    }
    

    I’ve attached a sample using alert('hello'). I would recommend getting the alert('hello') popup to appear as desired first and then debug from there. Everyones setup is different so this solution might need to be slightly tweaked. However, the principles should be the same.

    Login or Signup to reply.
  4. You are running your script on window.onload, which runs only once (First page load).

    To get around this behaviour, you should call the function manually on componentDidMount.

    Approach 1

    In your script.js you can assign the main function to the window object like below

    window.RotateText = function() {
      var elements = document.getElementsByClassName("txt-rotate");
      for (var i = 0; i < elements.length; i++) {
        var toRotate = elements[i].getAttribute("data-rotate");
        var period = elements[i].getAttribute("data-period");
        if (toRotate) {
          new TxtRotate(elements[i], JSON.parse(toRotate), period);
        }
      }
    };
    

    And in your About.js change componentDidMount to something like below.

      componentDidMount() {
        document.title = "About MA2WEB - Full-Stack Web Developer";
        if(window && window.RotateText){
            window.RotateText();
        }
      }
    

    Complete code.

    script.js

    var TxtRotate = function(el, toRotate, period) {
      this.toRotate = toRotate;
      this.el = el;
      this.loopNum = 0;
      this.period = parseInt(period, 10) || 2000;
      this.txt = "";
      this.tick();
      this.isDeleting = false;
    };
    
    TxtRotate.prototype.tick = function() {
      var i = this.loopNum % this.toRotate.length;
      var fullTxt = this.toRotate[i];
    
      if (this.isDeleting) {
        this.txt = fullTxt.substring(0, this.txt.length - 1);
      } else {
        this.txt = fullTxt.substring(0, this.txt.length + 1);
      }
    
      this.el.innerHTML = '<span class="wrap">' + this.txt + "</span>";
    
      var that = this;
      var delta = 300 - Math.random() * 100;
    
      if (this.isDeleting) {
        delta /= 2;
      }
    
      if (!this.isDeleting && this.txt === fullTxt) {
        delta = this.period;
        this.isDeleting = true;
      } else if (this.isDeleting && this.txt === "") {
        this.isDeleting = false;
        this.loopNum++;
        delta = 500;
      }
    
      setTimeout(function() {
        that.tick();
      }, delta);
    };
    
    window.RotateText = function() {
      var elements = document.getElementsByClassName("txt-rotate");
      for (var i = 0; i < elements.length; i++) {
        var toRotate = elements[i].getAttribute("data-rotate");
        var period = elements[i].getAttribute("data-period");
        if (toRotate) {
          new TxtRotate(elements[i], JSON.parse(toRotate), period);
        }
      }
    };
    
    window.onload = window.RotateText;
    

    About.js

    import React from "react";
    
    export default class About extends React.Component {
      componentDidMount() {
        document.title = "About MA2WEB - Full-Stack Web Developer";
        if(window && window.RotateText){
            window.RotateText();
        }
      }
      render() {
        return (
          <section className="main-section about animate">
            <article className="about-contents-ma2web">
              <h1 className="typing-ma2web">
                I have experience in{" "}
                <span
                  className="txt-rotate"
                  data-period="2000"
                  data-rotate='[ "JavaScript", "Reactjs", "Nodejs", "GSAP", "PHP", "MySQL", "Wordpress", "SEO" ]'
                ></span>
              </h1>
              <p>I can develop both client and server side languages.</p>
            </article>
          </section>
        );
      }
    }
    

    Approach 2.

    Export default function from script.js.

    export default function() {
      var elements = document.getElementsByClassName("txt-rotate");
      for (var i = 0; i < elements.length; i++) {
        var toRotate = elements[i].getAttribute("data-rotate");
        var period = elements[i].getAttribute("data-period");
        if (toRotate) {
          new TxtRotate(elements[i], JSON.parse(toRotate), period);
        }
      }
    }
    

    Import the function in any component you need.

    import rotateText from "../js/script";
    

    Call the function in componentDidMount.

      componentDidMount() {
        document.title = "About MA2WEB - Full-Stack Web Developer";
        if(window){
            rotateText();
        }
      }
    

    Complete code

    script.js

    var TxtRotate = function(el, toRotate, period) {
      this.toRotate = toRotate;
      this.el = el;
      this.loopNum = 0;
      this.period = parseInt(period, 10) || 2000;
      this.txt = "";
      this.tick();
      this.isDeleting = false;
    };
    
    TxtRotate.prototype.tick = function() {
      var i = this.loopNum % this.toRotate.length;
      var fullTxt = this.toRotate[i];
    
      if (this.isDeleting) {
        this.txt = fullTxt.substring(0, this.txt.length - 1);
      } else {
        this.txt = fullTxt.substring(0, this.txt.length + 1);
      }
    
      this.el.innerHTML = '<span class="wrap">' + this.txt + "</span>";
    
      var that = this;
      var delta = 300 - Math.random() * 100;
    
      if (this.isDeleting) {
        delta /= 2;
      }
    
      if (!this.isDeleting && this.txt === fullTxt) {
        delta = this.period;
        this.isDeleting = true;
      } else if (this.isDeleting && this.txt === "") {
        this.isDeleting = false;
        this.loopNum++;
        delta = 500;
      }
    
      setTimeout(function() {
        that.tick();
      }, delta);
    };
    
    export default function() {
      var elements = document.getElementsByClassName("txt-rotate");
      for (var i = 0; i < elements.length; i++) {
        var toRotate = elements[i].getAttribute("data-rotate");
        var period = elements[i].getAttribute("data-period");
        if (toRotate) {
          new TxtRotate(elements[i], JSON.parse(toRotate), period);
        }
      }
    }
    

    About.js

    import React from "react";
    import rotateText from "../js/script";
    
    export default class About extends React.Component {
      componentDidMount() {
        document.title = "About MA2WEB - Full-Stack Web Developer";
        if(window){
            rotateText();
        }
      }
      render() {
        return (
          <section className="main-section about animate">
            <article className="about-contents-ma2web">
              <h1 className="typing-ma2web">
                I have experience in{" "}
                <span
                  className="txt-rotate"
                  data-period="2000"
                  data-rotate='[ "JavaScript", "Reactjs", "Nodejs", "GSAP", "PHP", "MySQL", "Wordpress", "SEO" ]'
                ></span>
              </h1>
              <p>I can develop both client and server side languages.</p>
            </article>
          </section>
        );
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search