如何对ComponentWillMount进行授权检查?

时间:2018-02-24 20:46:57

标签: reactjs react-redux

我的网站有一些受登录保护的网页。我目前的解决方案是:

app.js中的

<div className="app">
        <Provider store={store}>
            <Router history={appHistory} onUpdate={fireTracking}>
                <Route name="main" component={AppHandler}>
                    <Route name="home" path="/" component={HomePageHandler}/>
                </Route>
            </Router>
        </Provider>
    </div>

然后我的HomePageHandler是:

export default class HomePageHandler extends BaseAuthorizedComponent {  
    render() {
        return (
            <div>hello</div>
        )
    }
}

由于HomePageHandler扩展了BaseAuthorizedComponent,它被定义为:

class BaseAuthorizedComponent extends Component {

    componentWillMount() {
        if (!this.props.user.signed_in) {
            this.context.router.push('/signin')
        }
    }
}

HomePageHandler.contextTypes = {
    router: React.PropTypes.object.isRequired,
}

function select(state) {
    return {
        user: state.user,
    }
}
export default connect(select)(BaseAuthorizedComponent)

redux的用户对象有一个标志,指示用户是否已登录。我们的想法是,在主页上,在安装组件之前,如果用户未登录,BaseAuthorizedComponent将检查并重定向到登录页面。我的想法是让每个需要授权的页面扩展BaseAuthorizedComponent。

但是,尝试加载主页时会发生以下错误:

Error: Could not find "store" in either the context or props of "Connect(BaseAuthorizedComponent)". Either wrap the root component in a <Provider>, or explicitly pass "store" as a prop to "Connect(BaseAuthorizedComponent)".

不知道如何在保持单个地方检查授权的优势的同时解决问题。有什么想法吗?谢谢!

4 个答案:

答案 0 :(得分:1)

首先,您最好使用合成而不是继承https://reactjs.org/docs/composition-vs-inheritance.html

接下来,您可以将react-action-redux(https://github.com/reactjs/react-router-redux)中的“推送”动作创建者添加到mapDispatchToProps函数中:

function composeAuth = (ComposedComponent) => {
    class BaseAuthorizedComponent extends React.Component {
        // We use componentDidMount instead of componentWillMount, cause componentWillMount is deprecated https://medium.com/@baphemot/whats-new-in-react-16-3-d2c9b7b6193b
        componentDidMount() {
            if (!this.props.user.signed_in) {
                this.props.push('/signin');
            }
        }
        
        render() {
            if (!this.props.user.signed_in) {
               return null;
            }
            
            return <ComposedComponent {...this.props} />
        }
    }
    
    return connect(state => ({user: state.user}), {push})(BaseAuthorizedComponent);
}

class HomePageHandler extends React.Component {  
    render() {
        return (
            <div>hello</div>
        )
    }
}

export default composeAuth(HomePageHandler);

答案 1 :(得分:0)

这个怎么样:

class CheckAuth extends React.Component{
   state = {
      auth: false
   }
   render(){
      return(
         {this.state.auth ? <div>Authorized user</div> : <div>Unauthorized user</div>}
      )
   }
}

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

export default connect(mapStateToProps)(CheckAuth);

然后将其包含在您的其他组件中:

import CheckAuth from './CheckAuth';
...
class Home extends React.Component{
   render(){
      return(
        <div>
           <CheckAuth />
           Hello world!!
        </div>
      )
   }
}

export default Home;

答案 2 :(得分:0)

经过更多研究,满足我要求的最简单方法是:

在util文件中:

export function requireAuth(nextState, replace) {
    // use your own method to check if user is logged in or not
    if (!isLoggedIn()) {
        replace({pathname: '/signin'});
    }
}

然后在app.js文件中导入此方法并使用它:

<div className="app">
        <Provider store={store}>
            <Router history={appHistory} onUpdate={fireTracking}>
                <Route name="main" component={AppHandler}>
                    <Route name="home" path="/" component={HomePageHandler} onEnter={requireAuth}/>
                </Route>
            </Router>
        </Provider>
    </div>

这样,如果用户需要auth(isLoggedIn()为false),那么它会将页面重定向到/ signin。

答案 3 :(得分:0)

经过一些研究,我见过的最好方法是:

<Route name="name" 
path="/path" 
component={THeWorkHandler} 
onEnter={requireAuth}/>

并且requireAuth被放在一个帮助文件中:

export function requireAuth(nextState, replace) {
    if (!(//logic to see if user is logged in )) {
        replace({pathname: '/user/signin'});
    }
}

这样,如果onEnter requireAuth确定用户未经过身份验证,则会重定向到/ user / signin页面。