te')); return $arr; } /* 遍历用户所有主题 * @param $uid 用户ID * @param int $page 页数 * @param int $pagesize 每页记录条数 * @param bool $desc 排序方式 TRUE降序 FALSE升序 * @param string $key 返回的数组用那一列的值作为 key * @param array $col 查询哪些列 */ function thread_tid_find_by_uid($uid, $page = 1, $pagesize = 1000, $desc = TRUE, $key = 'tid', $col = array()) { if (empty($uid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('uid' => $uid), array('tid' => $orderby), $page, $pagesize, $key, $col); return $arr; } // 遍历栏目下tid 支持数组 $fid = array(1,2,3) function thread_tid_find_by_fid($fid, $page = 1, $pagesize = 1000, $desc = TRUE) { if (empty($fid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('fid' => $fid), array('tid' => $orderby), $page, $pagesize, 'tid', array('tid', 'verify_date')); return $arr; } function thread_tid_delete($tid) { if (empty($tid)) return FALSE; $r = thread_tid__delete(array('tid' => $tid)); return $r; } function thread_tid_count() { $n = thread_tid__count(); return $n; } // 统计用户主题数 大数量下严谨使用非主键统计 function thread_uid_count($uid) { $n = thread_tid__count(array('uid' => $uid)); return $n; } // 统计栏目主题数 大数量下严谨使用非主键统计 function thread_fid_count($fid) { $n = thread_tid__count(array('fid' => $fid)); return $n; } ?>javascript - React Router redirect hash link - Stack Overflow
最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - React Router redirect hash link - Stack Overflow

programmeradmin3浏览0评论

I have created a custom button ponent for my website's navbar. When the user clicks on a button, the ponent returns a Redirect, which takes the user to the page they selected.

export default class Button extends Component {
    constructor(props){
        super(props);
        this.state = {redirect:false};
        this._handleClick = this._handleClick.bind(this);
    }

    _handleClick(e) {
        e.stopPropagation();
        this.setState({redirect: true});
    }

    ponentDidUpdate() {
        if (this.state.redirect){
            this.setState({redirect:false});
            this.props.onRedirect();
        }
    }

    render() {
        if (this.state.redirect){
            return <Redirect push to={this.props.dest}/>;
        }
        else {
            return (
                <li className="button" onClick={this._handleClick}>
                    <h5>{this.props.text}</h5>
                </li>
            );
        }
    }
}

Now, I'd like to add buttons that correspond to different sections of the same page. The simplest way I know of is to use hash links. One example of an address the button would redirect to is:

/home#description

However, React Router does not support doing this out of the box. I looked through a number of packages which add this functionality, such as react-router-hash-link and react-scrollchor. None of these however work with redirects, instead relying on Link or on custom ponents.

How do I go about adding this functionality to the buttons?

I have created a custom button ponent for my website's navbar. When the user clicks on a button, the ponent returns a Redirect, which takes the user to the page they selected.

export default class Button extends Component {
    constructor(props){
        super(props);
        this.state = {redirect:false};
        this._handleClick = this._handleClick.bind(this);
    }

    _handleClick(e) {
        e.stopPropagation();
        this.setState({redirect: true});
    }

    ponentDidUpdate() {
        if (this.state.redirect){
            this.setState({redirect:false});
            this.props.onRedirect();
        }
    }

    render() {
        if (this.state.redirect){
            return <Redirect push to={this.props.dest}/>;
        }
        else {
            return (
                <li className="button" onClick={this._handleClick}>
                    <h5>{this.props.text}</h5>
                </li>
            );
        }
    }
}

Now, I'd like to add buttons that correspond to different sections of the same page. The simplest way I know of is to use hash links. One example of an address the button would redirect to is:

/home#description

However, React Router does not support doing this out of the box. I looked through a number of packages which add this functionality, such as react-router-hash-link and react-scrollchor. None of these however work with redirects, instead relying on Link or on custom ponents.

How do I go about adding this functionality to the buttons?

Share Improve this question asked Aug 24, 2017 at 14:44 steliosblsteliosbl 8,9214 gold badges31 silver badges57 bronze badges
Add a ment  | 

7 Answers 7

Reset to default 2

you could update window.location.href since it won't trigger a page refresh.

e.g.

window.location.href = '#your-anchor-tag';

One solution that I can think of is to use HOCs and hooks. The end result:

  • You'll get your app to scroll to the specified location...
  • without really needing to create custom buttons/links and...
  • without making much changes to your existing screens (Eg: HomeScreen)
  • Bonus: Users can copy, share & use URLs that will automatically scroll to the intended section


With assumption that the code below are pseudocode (they are based on my knowledge and not tested) and assuming there's a HomeScreen ponent, I would attempt adding <Route/>s to the <Switch/> inside the <Router/>.

<Switch>
  <Route to='/home/:section' ponent={HomeScreen} />
  <Route to='/home' ponent={HomeScreen} />
</Switch>


Then:

function withScrollToTarget(WrappedComponent) {
  class WithScroll extends React.Component {
    ponentDidMount() {
      const { match: { params: { section } } } = this.props
      // Remember we had 2 <Route/>s, so if `section` is provided...
      if (section) {
        const scrollToTarget = document.getElementById(section)
        // And just in case the item was removed or there was an ID mismatch
        if (scrollToTarget) { scrollToTarget.scrollIntoView() }
      }
    }
    render() { return <WrappedComponent {...this.props} /> }
  }
  return WithScroll
}

function useScrollToTarget(section) {
  useEffect(() => {
    if (section) {
      const scrollToTarget = document.getElementById(section)
      if (scrollToTarget) { scrollToTarget.scrollIntoView() }
    }
  }, [section])
}


Usage:

<nav>
  <Link to='/home'>{'Home'}</Link>
  <Link to='/home/description'>{'Description'}</Link>
</nav>


class HomeScreen extends React.Component { /* ... */ }
export default withScrollToTarget(HomeScreen)
// or
function HomeScreen() {
  const { params: { section } } = useMatch() // from react-router-dom
  useScrollTotarget(section)
  return (
    <div>
      <h1 id='introduction'>Introduction</h1>
      <h1 id='description'>Description</h1>
    </div>
  )
}


TLDR:

  • The route for '/home/:section' must be on top of '/home'. If the opposite, every time when <Switch/> pares the current URL against to, it will evaluate to true upon reaching '/home' and never reach '/home/:section'
  • scrollIntoView() is a legit function
  • If this works for you, you should look up on how to forward refs and hoisting statics in HOCs too

Who said React Router doesn't support this out of the box! You don't need those packages. You can redirect a hash i'll give you an example using the React-Router Route.

<Route
  exact
  path="/signup"
  render={props => {
    if (props.location.hash === "#foo")
      return <Redirect push to="signup#bar"
    return <Signup />
  }}
/>

Now your version may not have supported this now that I think about it, but let me know if this helps :) Happy coding!

React-hash-link should work for your redirect use case.

You can add <HashLinkObserver /> to your ponent tree and it will listen for hash links and scroll accordingly rather than relying on Link or custom ponents.

I think you should use the react-router-dom.

yarn add react-router-dom

Now update Custom Button Component like this

import React from 'react';
import { withRouter } from "react-router-dom";
class Button extends Component {
    constructor(props){
        super(props);
        this.state = {redirect:false};
        this._handleClick = this._handleClick.bind(this);
    }

    _handleClick(e) {
        e.stopPropagation();
        this.setState({redirect: true});
    }

    ponentDidUpdate() {
        if (this.state.redirect){
            this.setState({redirect:false});
            //this.props.onRedirect();
            this.props.history.push('new uri');
        }
    }

    render() {
        if (this.state.redirect){
            return <Redirect push to={this.props.dest}/>;
        }
        else {
            return (
                <li className="button" onClick={this._handleClick}>
                    <h5>{this.props.text}</h5>
                </li>
            );
        }
    }
}
export default withRouter(Button);

I was trying to solve a similar but slightly different issue, I want to deprecate an old hash route in favor of a new one. The posts here helped me arrive to my eventual solution:

<Route
    exact
    path={'/thing/:id'}
    render={({
        match: {
            params: { id },
        },
    }) => (
        <Redirect
            push
            to={`/newThing/${id}`}
        />
    )}
/>

I was facing the same issue, I have created HOC to handle hash redirection, you can follow the below steps to achieve a hash redirection

  1. create HOC and add below code to it

fileName : hashComponent

import React, { useEffect } from 'react';

export default function hashComponent(WrappedComponent) {

  return function () {
    const { pathname, hash }=window.location;
    useEffect(() => {

      if(hash)
        window.location.href=`${pathname}${hash}`;
    }, [hash])

    return <WrappedComponent />
  }
}
  1. import your HOC in the ponent to which you want to handle hash URL

  2. Then add below line of code while exporting your ponent

    export default hashComponent(YourComponentName)

发布评论

评论列表(0)

  1. 暂无评论