高阶函数渲染两次导致子组件被触发

higher order function render twice causing child component to be triggered

我有一个受保护的路由,使用高阶组件实现,但是在我的App.js子组件中,触发它的componentDidMount方法,我想知道为什么会这样..

Route.js

...
<BrowserRouter>
  <Switch>
    <Route exact path='/app' component={CheckPermission(App)} />
    <Route exact path='/app/login' component={Login} />
  </Switch>
</BrowserRouter>
...

Auth.js

export default function CheckPermission(EnhancedComponent) {
  class Auth extends Component {
    static contextTypes = {
      router: PropTypes.object
    }

    componentWillMount() {
      if (!this.props.isAuth) {
        this.context.router.history.replace(`/login`)
      }
    }

    componentWillUpdate() {
      if (!this.props.isAuth) {
        this.context.router.history.replace(`/login`)
      }
    }

    render() {
      return <EnhancedComponent { ...this.props } />
    }
  }

  return connect()(Auth)
}

App.js

class App extends Component {
  componentDidMount(){
    console.log('test') //why is this trigger??
  }
  render() {
    return <h1>App</h1>
  }
}

如果我在 App.js 的 componentDidMount 中有 API 调用,它会导致不需要的调用,我认为 Auth.js 的 componentWillMount 已经阻止渲染触发了?我在浏览器中看到,Auth.js 的重定向刚刚起作用。

无法保证 componentWillMount 中的 replace 方法会在 render 方法触发之前重定向。

您可能希望将 Auth.js 代码重构为类似这样的代码。

export default function CheckPermission(EnhancedComponent) {
  class Auth extends Component {
    render() {
      // Note that we return a <Redirect /> component here early for not giving <EnhancedComponent /> any chance to render itself.
      if (!this.props.isAuth) {
        return <Redirect to="/login" />
      }

      return <EnhancedComponent { ...this.props } />
    }
  }

  return connect()(Auth)
}