具有更高阶React Redux组件的无限循环

时间:2018-02-07 21:06:54

标签: reactjs redux

使用高阶组件处理经过身份验证的路由时,我遇到了无限循环问题。身份验证非常基本,在redux状态下只是一个true或false的布尔值。

当应用程序最初启动时,它会检查是否有用户存储在localStorage中。如果它不返回null,我们会立即发送一个SIGN_IN操作。

import React from 'react'
import ReactDOM from 'react-dom'
import { HashRouter } from 'react-router-dom'
import { Provider } from 'react-redux'
import { createStore, applyMiddleware } from 'redux'
import reducers from './reducers'
import reduxThunk from 'redux-thunk'
import { SIGN_IN } from './actions/types'

import logger from 'redux-logger'
const createStoreWithMiddleware = applyMiddleware(reduxThunk, logger)(createStore)
const store = createStoreWithMiddleware(reducers)

import App from './components/App'


const user = localStorage.getItem('user')
if(user) {
  store.dispatch({ type: SIGN_IN })
}

ReactDOM.render (
  <Provider store={store}>
    <HashRouter>
      <App />
    </HashRouter>
  </Provider>,
  document.querySelector('.main')
)

这是高阶组件

import React, { Component } from 'react';
import { connect } from 'react-redux';

export default function(ComposedComponent) {
  class RequireAuth extends Component {

    componentWillMount = () => {
      if(!this.props.auth)
        this.props.history.push('/')
    }

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

  function mapStateToProps(state) {
    return { auth: state.auth };
  }

  return connect(mapStateToProps)(RequireAuth);
}

componentWillMount中的逻辑似乎是导致无限循环的原因,但我真的不知道为什么。这似乎阻止我去任何其他路线,但正如你在下面的控制台输出中看到的那样,它会以非凡的方式爆发。

enter image description here

如果有帮助,这里是组件,我用HOC包装我的组件。

export default class App extends Component {
  constructor(props) {
    super(props)
  }

  render() {

    return (
      <div className="app"
        style={{
          backgroundImage: 'url("./img/base-bg.jpg")',
          backgroundSize: 'cover',
          backgroundPosition: 'center center',
          backgroundRepeat: 'no-repeat'
        }}
      >

        <Switch>
          <Route path="/" exact component={RequireAuth(Intro)} />
          <Route path="/landing" exact component={RequireAuth(Intro)} />
          <Route path="/journey" component={RequireAuth(Exhibit)} />
          <Redirect to="/landing" />
        </Switch>

       <Footer />
      </div>
    )
  }
}

如果有帮助,我正在使用React Router V4。为了澄清,包含登录表单和登录页面。如果用户未经过身份验证,则介绍会显示登录表单,并且在初始化时,应显示登录页面。也许这就是我弄乱的地方,不应该嵌套我的组件。我不确定。

1 个答案:

答案 0 :(得分:0)

这归结为hackalicious nesting以及我如何使用RequireAuth包装我的组件。我没有在名为Intro的组件中进行登录和着陆,而是取消了该操作并将路由配置更改为:

<Switch>
  <Route path="/" exact component={Login} />
  <Route path="/landing" exact component={RequireAuth(Landing)} />
</Switch>

现在这是我的HOC,几乎一样。

export default function(ComposedComponent) {
  class RequireAuth extends Component {

    componentDidMount = () => {
      if(!this.props.auth)
        this.redirectToLogin()
    }

    componentWillUpdate = nextProps => {
      if(!nextProps.auth)
        this.redirectToLogin()
    }

    redirectToLogin = () => this.props.history.push('/')

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

  function mapStateToProps(state) {
    return { auth: state.auth };
  }

  return connect(mapStateToProps)(RequireAuth);
}