【问题标题】:Why React-router v4 <Link/> does not work (Changes url but not rendering content)?为什么 React-router v4 <Link/> 不起作用(更改 url 但不呈现内容)?
【发布时间】:2017-12-08 10:21:15
【问题描述】:

我有服务器端 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)

需要从 导航栏

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 url 会更新,但 App Switch 不会。当 loginRedirect to /login 没有出现并且需要刷新页面时,我也有一个问题(可能这两个是相关的)。 如何解决这个问题?

【问题讨论】:

    标签: javascript reactjs react-router


    【解决方案1】:

    我认为这里的问题在于 redux .. 因为只要 props 没有改变,它就会阻止重新渲染组件,

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

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

    如果由于某种原因不可行(例如,如果您使用的库严重依赖于 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

    【讨论】:

    • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接的答案可能会失效
    • 已编辑.. 谢谢@ThomasVd Berge
    【解决方案2】:

    如果使用 Redux,redux connect HOC 会覆盖组件上的 shouldComponentUpdate 生命周期方法并检查 props 和状态更改,这可能会混淆 React Router。用户点击链接之类的操作不一定会按原样更改状态或道具,从而导致不会在路由上下文中重新渲染组件。

    react router 的文档说明了这个问题的解决方案:

    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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-08-31
      • 2023-01-12
      • 2019-11-23
      • 2018-04-23
      • 2020-02-12
      • 2021-05-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多