如何使用localStorage正确连接到Horizo​​n?

时间:2018-01-12 01:18:02

标签: javascript reactjs horizon

我正在尝试实现Horizo​​n Server(Express.js + RethinkDB)和React.js Horizo​​n Client(React + Material-UI)。这是两个独立的应用程序。

我找到了一个关于如何在Horizo​​n中设置自定义登录的非常好的示例:https://github.com/tailsu/horizon-custom-login所以我已经开始将其配置为后端。

我正在尝试实施Horizo​​n,Horizo​​n需要一个session_token而不确定在何处放置Horizo​​n的连接字符串,我有一个登录表单,我收到会话令牌,我将其保存到localStorage但是当页面加载localStorage似乎是空的。

如果我重新加载页面,令牌就会起作用,一切似乎都没问题。

有谁知道如何正确处理?

这是我目前的代码:

仪表板:

            import React from 'react';
            import {Link, withRouter} from 'react-router-dom';
            import axios from 'axios';
            import {backendUrl, backendApiKey, apiRequestRate} from '../../config';
            import {Redirect} from 'react-router';
            import AppBar from 'material-ui/AppBar';
            import Toolbar from 'material-ui/Toolbar';
            import IconButton from 'material-ui/IconButton';
            import Typography from 'material-ui/Typography';
            import AccountCircle from 'material-ui-icons/AccountCircle';
            import Menu, {MenuItem} from 'material-ui/Menu';
            import PropTypes from 'prop-types';
            import Tabious from './tabious';
            import {dashTheme} from '../../themes/dashTheme';
            import Horizon from '../../horizon-container';
            import LoginForm from '../login';
            const _horizon = Horizon.get();

            class Dashboard extends React.Component {
                constructor(props, context) {
                    super(props, context);
                    this.state = {
                        token: localStorage.getItem('session_token')
                    }
                }
                static contextTypes = {
                    router: PropTypes.object
            }
                state = {
                    anchorEl: null
                };
                componentDidMount(){
                    _horizon.connect();
                    this.timer = setInterval(() => {
                        if(_horizon.hasAuthToken() == false){
                        console.log('why???');
                        }
                    }, 1000);
                }
                componentWillUnmount(){
                    clearInterval(this.timer);
                }
                handleMenu = event => {
                    this.setState({anchorEl: event.currentTarget});
                };
                handleRequestClose = () => {
                    this.setState({anchorEl: null});
                };
                handleLogOut = (props) => {
                    localStorage.removeItem('session_token');
                    Horizon.clearAuthTokens();
                    this.context.router.history.push("/login");
                };
                handleMyAcc = (event : any, value : any) => {
                    this.context.router.history.push(value);
                };
                render() {
                    const {anchorEl} = this.state;
                    const open = Boolean(anchorEl);
                    return (
                    <div>
                        <AppBar style={dashTheme.bar}>
                                <Toolbar>
                                    <Link to="/">
                                        <IconButton color="contrast" aria-label="Menu">
                                            <img src="/logoico.png" alt=""/>
                                        </IconButton>
                                    </Link>
                                    <Typography type="title" style={dashTheme.typo}>
                                        Chalton PMS
                                    </Typography>
                                    <Tabious/>
                                    <div>
                                        <IconButton aria-owns={open
                                                    ? 'menu-appbar'
                                                    : null} aria-haspopup="true" onClick={this.handleMenu} color="contrast">
                                            <AccountCircle/>
                                        </IconButton>
                                        <Menu id="menu-appbar" anchorEl={anchorEl} anchorOrigin={{
                                                    vertical: 'top',
                                                    horizontal: 'right'
                                            }} transformOrigin={{
                                                    vertical: 'top',
                                                    horizontal: 'right'
                                            }} open={open}
                                            onClose={this.handleRequestClose}
                                            >
                                            <MenuItem onClick={this.handleLogOut}>Log Out</MenuItem>
                                            <MenuItem onTouchTap={() => {
                                                        this.context.router.history.push('/myaccount')
                                                    }}>My account</MenuItem>
                                        </Menu>
                                    </div>
                                </Toolbar>
                        </AppBar>
                        {this.props.children}
                                                </div>
                    );
                }
            }
            export default withRouter(Dashboard);

Horizo​​n Container:

            import Horizon from '@horizon/client';
            import {backendUrl} from './config';
            console.log(localStorage.getItem('session_token'));
            const _horizon = Horizon({host: backendUrl, authType: {token: localStorage.getItem('session_token'), storeLocally: true}});

            export default { 
                get: () => _horizon, 
                clearAuthTokens: () => Horizon.clearAuthTokens() 
            }

登录:

            import React from 'react';
            import {Redirect} from 'react-router';
            import axios from 'axios';
            import {withRouter} from 'react-router-dom';
            import {MuiThemeProvider} from 'material-ui/styles';
            import Paper from 'material-ui/Paper';
            import AppBar from 'material-ui/AppBar';
            import Toolbar from 'material-ui/Toolbar';
            import IconButton from 'material-ui/IconButton';
            import Typography from 'material-ui/Typography';
            import Button from 'material-ui/Button';
            import PropTypes from 'prop-types';
            import {ValidatorForm, TextValidator} from 'react-material-ui-form-validator';
            import {loginUrl} from '../config';
            import Dashboard from './dashboard/dashboard';
            import {loginTheme} from '../themes/loginTheme';

            class LoginForm extends React.Component {
                constructor(props,context) {
                    super(props,context);
                    this.state = {
                        login: {
                                username: '',
                                pwd: ''
                        },
                        token: localStorage.getItem('session_token')
                    };
                    this.handleSubmit = this.handleSubmit.bind(this);
                }
                static contextTypes = {
                    router: PropTypes.object
            }

                handleChange(property, event) {
                    const login = {
                        ...this.state.login
                    };
                    login[property] = event.target.value;
                    this.setState({login});
                }

                handleSubmit(event) {
                    let payload = 'username=' + this.state.login.username + '&password=' + this.state.login.pwd;
                    let headers = {
                        'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
                    };          
                    let self = this;
                    axios.post(loginUrl + '/login', payload, headers).then(function(response) {
                        localStorage.setItem('session_token', response.data.token);
                        localStorage.setItem('session_user', self.state.login.username);
                        self.context.router.history.push("/");
                            }).catch(function(error) {
                        self.setState({'ErrorMSG': 'These authentication details are invalid.'});
                    });
                    event.preventDefault();
                }
                render() {
                    if(this.state.token){
                        <Redirect to="/" />
                    }

                    return(
                    <div>
                        <MuiThemeProvider theme={loginTheme}>
                                <div>
                                    <Paper style={loginTheme.paper}>
                                        <AppBar position="static" style={loginTheme.bar}>
                                            <Toolbar>
                                                    <IconButton color="contrast" aria-label="Menu">
                                                        <img src="/logoico.png" alt=""/>
                                                    </IconButton>
                                                    <Typography type="title" style={loginTheme.typo}>
                                                        Chalton PMS
                                                    </Typography>
                                            </Toolbar>
                                        </AppBar>
                                        <ValidatorForm ref="form" onSubmit={this.handleSubmit} onError={errors => console.log(errors)}>
                                            <TextValidator label="Username" name="username" style={loginTheme.tf} value={this.state.login.username} onChange={this.handleChange.bind(this, 'username')} validators={['required']} errorMessages={['This field is required.', 'Username is not valid.']}/>
                                            <TextValidator label="Password" name="password" type="password" style={loginTheme.tf} value={this.state.login.pwd} onChange={this.handleChange.bind(this, 'pwd')} validators={['required']} errorMessages={['This field is required.']}/>
                                            <p style={loginTheme.errorMSG}>{this.state.ErrorMSG}</p>
                                            <Button raised type="submit" style={loginTheme.loginBTN} color="primary">
                                                    Login
                                            </Button>
                                        </ValidatorForm>
                                    </Paper>
                                </div>
                        </MuiThemeProvider>
                    </div>
                );   
                }

            }

            export default withRouter(LoginForm);

1 个答案:

答案 0 :(得分:0)

如果我把容器放在后面,它似乎正在工作。

仪表板中的代码:

        componentDidMount(){
            const _horizon = new Horizon({host: backendUrl, authType: {token: localStorage.getItem('session_token'), storeLocally: true}});
            _horizon.connect();
            console.log(_horizon.status());
            this.timer = setInterval(() => {
                if(_horizon.hasAuthToken() == false){
                this.handleLogOut
                }
            }, 1000);
        }