【问题标题】:higher order function render twice causing child component to be triggered高阶函数渲染两次导致子组件被触发
【发布时间】:2018-03-25 14:47:21
【问题描述】:

我有一个受保护的路由,使用高阶组件实现,但是在我的作为子组件的 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 的重定向刚刚起作用。

【问题讨论】:

    标签: javascript reactjs redux higher-order-components


    【解决方案1】:

    不保证componentWillMount 中的替换方法会在渲染方法触发之前重定向。

    您可能希望将您的 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)
    }
    

    【讨论】:

    • 那么使用HOC没有生命周期方法吗?你能澄清一下There is no guarantee 吗?
    • @JamieAden 您不必在 HOC 中使用生命周期方法。因为基本上你在componentWillMount 中所做的是一个副作用,它在安装之前同步运行。 react-router 在&lt;Route /&gt; 中也做了类似的事情来检查你的url是否匹配某种模式。因此,在您将子组件实际重定向到父组件之前,子组件很可能会被挂载。
    • @JamieAden 另外,我们应该防止在componentWilMount 中引入任何副作用,因为它会像您的代码一样产生一些意想不到的行为。实际上我们应该完全避免使用componentWillMount,但这是另一种情况。
    • 试过你上面的代码,不行,上面的流程正确吗?我进入了无限循环
    • @JamieAden 当然可以,只需在componentDidMount 或安全的地方进行操作,然后致电setState。在您的渲染方法中,您可以根据您当前的state 有条件地渲染不同的组件。不过,这超出了这个范围。
    猜你喜欢
    • 1970-01-01
    • 2020-07-14
    • 1970-01-01
    • 1970-01-01
    • 2013-12-25
    • 1970-01-01
    • 1970-01-01
    • 2022-06-12
    • 1970-01-01
    相关资源
    最近更新 更多