javascript - React: Stop page reload on clicking on anchor tag for scrolling - Stack Overflow

I am currently using react to create a Wikipedia style website. For data entry reasons, I am fetching a

I am currently using react to create a Wikipedia style website. For data entry reasons, I am fetching an entire HTML from the database and then using dangerouslySetInnerHTML to set some part of it, like so:

dangerouslySetInnerHTML={{ __html: this.props.section.text }}

Now there are other parts of the page that have a video playing in it, however every time I click on an <a href="#id> style tag (set using the database) to navigate to another part of the same page, the entire page refreshes.

This creates a problem since the video reloads as well and starts playing from the beginning.

Is there any way to use a dangerously set anchor tag to scroll to parts of a page in React without full page reload?

Edit: Using following versions:

"react": "^16.0.0", "react-router-dom": "^4.2.2"

I am currently using react to create a Wikipedia style website. For data entry reasons, I am fetching an entire HTML from the database and then using dangerouslySetInnerHTML to set some part of it, like so:

dangerouslySetInnerHTML={{ __html: this.props.section.text }}

Now there are other parts of the page that have a video playing in it, however every time I click on an <a href="#id> style tag (set using the database) to navigate to another part of the same page, the entire page refreshes.

This creates a problem since the video reloads as well and starts playing from the beginning.

Is there any way to use a dangerously set anchor tag to scroll to parts of a page in React without full page reload?

Edit: Using following versions:

"react": "^16.0.0", "react-router-dom": "^4.2.2"

Share Improve this question edited Nov 9, 2017 at 11:27 Kehkashan Fazal asked Nov 9, 2017 at 11:07 Kehkashan FazalKehkashan Fazal 7811 gold badge6 silver badges8 bronze badges 2
  • Which version of react-router are you using? – Chris Commented Nov 9, 2017 at 11:15
  • @Chris I am using [email protected] – Kehkashan Fazal Commented Nov 9, 2017 at 11:26
Add a ment  | 

5 Answers 5

Reset to default 3

What you could do is to add an eventListener to your ponent which listens to all anchor tags whose href attribute value start with #.

Inside your ponentDidMount() method, select all your <a> tags where href="#...". You can do this with document.querySelectorAll("a[href^='#']"). That will return an array of all nodes that were matched. You can then loop through them and attach an eventListener to each one.

The eventListener would listen to click and run a function which prevents the default behavior (redirect to another page) and instead push to your router. (Remove the ment below)

class MyApp extends React.Component {

  constructor(props) {
    super(props);
  }

  ponentDidMount() {
    document.querySelectorAll("a[href^='#']").forEach(node => {
      node.addEventListener('click', e => {
        e.preventDefault();
        console.log(e.target.href);
        //this.props.history.push(e.target.href);
      });
    })
  }
 
  render() {
    const myMarkup = "<ul><li><a href='#'>Page link 1</a></li><li><a href='#test'>Page link 2</a></li><li><a href='https://google.'>External link</a></li></ul>";
    return(
      <div id="container" dangerouslySetInnerHTML={{__html: myMarkup}}></div>
    );
  }
}
 
ReactDOM.render(<MyApp />, document.getElementById("app"));
<script src="https://cdnjs.cloudflare./ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>

The above snippet assumes you are using the withRouter HOC. Otherwise the push won't work. For more info, see my answer to How to push to History in React Router v4?.

catch default eventhandler and handle event handling yourself. you can put this in ponentDidMount lifecycle hook. Also remove these handlers in ponentWillUnmount

var aTags = document.querySelectorAll('a[href]'); //use apt selector for you section


     aTags.forEach(aTag =>aTag.addEventListener('click',function(e){
          e.preventDefault();
          e.nativeEvent.stopImmediatePropagation()
          e.stopPropagation()
          var href = e.target.href;
          history.pushState({},'',href);
        }));

To add onto what @Shishir Arora was saying, instead of using history.pushState({},'',href); use something like document.getElementById(hash.replace('#', '')).scrollIntoView();.

Here's code for a full ponent where I leverage jQuery:

import React, { useEffect } from 'react';
import $ from 'jquery';

const handleAnchorClick = e => {
  e.preventDefault();
  e.stopPropagation();

  const hash = e.currentTarget.hash;
  document.getElementById(hash.replace('#', '')).scrollIntoView();
  // Alternatively use jQuery for the above line: $(hash).get(0).scrollIntoView();
};

export default ({ response, url, search }) => {
  useEffect(() => {
    $('#article-content').on('click', 'a[href^="#"]', handleAnchorClick);

    return () => {
      $('#article-content').off('click', 'a[href^="#"]', handleAnchorClick);
    };
  }, [response]);

  return (
    <div>
      <div id='article-content' dangerouslySetInnerHTML={{__html: response}} />
    </div>
  );
};

jQuery was helpful in capturing the currentTarget which won't get captured the same way with @Shishir's original answer because of an element nested within the tag.

Since your question has the tag "react-router" I assume you use it in your application, I also assume you are using the latest version which v4.x.

The way I have tackled this in the past was using React Router Hash link package. As is noted in their documentation, you can use it like that (replace your <a href="#id"> with <Link>):

// In YourComponent.js
...
import { HashLink as Link } from 'react-router-hash-link';
...
// Use it just like a RRv4 link (to can be a string or an object, see RRv4 api for details):
<Link to="/some/path#with-hash-fragment">Link to Hash Fragment</Link>

Since you're using React Router v4, why don't you use Link?

...
import { Link } from 'react-router-dom';
... 
<Link to={{
  pathname: '/courses',
  search: '?sort=name',
  hash: '#the-hash',
  state: { fromDashboard: true }
}}/>

You can find the documentation here.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1742372267a4431478.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信