Мой сайт имеет несколько страниц, защищенных логином. Мое текущее решение этого:

В 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)

Пользовательский объект редуктора имеет флаг, который указывает, вошел ли пользователь в систему или нет. Идея состоит в том, что на домашней странице перед монтированием компонента 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)".

Не знаю, как можно решить проблему, сохранив преимущество одного места для проверки авторизации. Какие-нибудь мысли? Спасибо!

0
jamesdeath123 24 Фев 2018 в 23:46

4 ответа

Лучший ответ

После некоторых исследований, лучший способ, который я видел, это:

<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.

0
jamesdeath123 29 Май 2018 в 19:25

Как насчет этого:

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;
0
Singh 24 Фев 2018 в 22:44

После дальнейших исследований самый простой способ удовлетворить мои требования:

В файле утилиты:

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.

0
jamesdeath123 26 Фев 2018 в 03:33

Прежде всего вам лучше использовать композицию вместо наследования https://reactjs.org/ документы / состав - против- inheritance.html

Далее, вы можете добавить создателя «push» действий изact-router-redux (https: // github .com / reactjs / реагировать-маршрутизатор-избыточность) для функции 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
Nik 24 Фев 2018 в 21:29