为什么React-router v4 <link />不起作用(更改网址但不提取内容)?

时间:2017-07-04 22:05:49

标签: javascript reactjs react-router

我有服务器端React / Redux / Express应用程序。 React-router v4为使用Switch的服务器应用程序提供解决方案,我需要使用一些东西来改变我的NavBar组件的位置

应用

import React, { Component } from 'react'

import { connect } from 'react-redux'
import { bindActionCreators } from 'redux'

import { Switch, Route, Redirect, Link} from 'react-router-dom'
import FirstPage from './FirstPage'
import Test from './Test'
import LoginPage from './login/LoginPage'
import NoMatch from '../components/NoMatch'
import NavBar from '../components/NavBar'

import * as loginActions from '../actions/login'

import 'bootstrap/dist/css/bootstrap.css';

class App extends Component {

  render(){
    return (
      <div>
            <NavBar/>

            <h1>EffortTracker v3.0.1</h1>

        <Switch >
            <Route exact path="/" render={loginRedirect(<FirstPage/>)}/>
              <Route path="/first" render={loginRedirect(<FirstPage/>)}/>
              <Route path="/second" render={loginRedirect(<Test/>)}/> />
              <Route path="/login" render={()=><LoginPage {...this.props.login}/>} />
              <Route component={NoMatch}/>
        </Switch>

          <Link to={'/first'}>First</Link>
      </div>
    )
  }
}

const loginRedirect=(component) => {
    if(!isLoggedIn()) return ()=> <Redirect to='login'/>

    return ()=> component
}

const isLoggedIn= ()=>{
    let token = localStorage.getItem('token')

if (token !== null)return false
    else return true

}

const mapStateToProps = state => ({
    login: state.login,
    error: state.error,
    isLoading: state.isLoading,
})

const mapDispatchToProps = dispatch => ({
    loginActions: bindActionCreators(loginActions, dispatch)
})

export default connect(
    mapStateToProps,
    mapDispatchToProps
)(App)

需要改变 的的NavBar

import React from 'react'
import { Link, NavLink } from 'react-router-dom'

import classnames from 'classnames'

const NavBar =()=> {
    return (
        <nav className={classnames("navbar", "navbar-inverse bg-inverse")}>
            <form className="form-inline">
                <Link to={'/'}>
                    <button className={classnames("btn", "btn-sm", "align-middle", "btn-outline-secondary")}
                            type="button">
                        Smaller button
                    </button>
                </Link>

                <NavLink to='/login'>
                    Login
                </NavLink>
            </form>

        </nav>
    )
  }

export default NavBar

如果我从浏览器URL手动导航它的工作就好了,但如果我点击链接或NavLink网址已更新但不是应用程序切换。当loginRedirect到/ login它没有出现并且需要刷新页面时我也遇到了问题(可能这两个是相关的)。 如何解决这个问题?

2 个答案:

答案 0 :(得分:3)

我认为这里的问题是使用redux ..因为只要道具没有改变就会阻止重新渲染组件,

  

这是因为connect()默认实现了shouldComponentUpdate,假设你的组件在给定相同的props和state的情况下会产生相同的结果。

     

最好的解决方案是确保您的组件是纯净的,并通过道具将任何外部状态传递给它们。这将确保您的视图不会重新渲染,除非它们实际上需要重新渲染并且会大大加快您的应用程序。

     

如果由于某种原因这不可行(例如,如果你使用的库严重依赖于React上下文),你可以将pure:false选项传递给connect():

function mapStateToProps(state) {
  return { todos: state.todos }
}

export default connect(mapStateToProps, null, null, {
  pure: false
})(TodoApp)

这里有更多解释的链接:

react-redux troubleshooting section

react-router DOCS

答案 1 :(得分:0)

如果使用Redux,则redux connect HOC将覆盖组件上的shouldComponentUpdate生命周期方法,并检查道具和状态更改,这可能会使React Router感到困惑。诸如用户单击链接之类的东西不一定会按原样更改状态或道具,从而不会在路由上下文中重新呈现组件。

react路由器的文档说明了此问题的解决方案:

withRouter HOC包裹组件

    import { Route, Switch, withRouter } from 'react-router-dom';
    import { connect } from 'react-redux';

    const Main = (props) => (
    <main>
      <Switch>
        <Route exact path='/' component={SAMPLE_HOME}/>
        <Route path='/dashboard' component={SAMPLE_DASHBOARD}/>    
      </Switch>
    </main>
      )
    export default withRouter(connect()(Main))  

此外,由于封闭的路线组件将传递具有location属性的道具,因此您可以将其传递给子组件,并且应该实现所需的行为。

https://reacttraining.com/react-router/web/guides/dealing-with-update-blocking