2017-07-02 53 views
1

我试图学习反应,但当我设置已验证的道具时,我被困在获取头组件的重新渲染。我一直在阅读它,但有很多不同的编码风格,我似乎无法有效地实现它们中的任何一种。我试图让它在this.props.authenticated更改时重新呈现。这是我最近的尝试,我无法让它在代码的小部分工作,所以我认为我会做整个块。当我更新商店时,我的一个控制器没有渲染

import React, { Component, PropTypes } from 'react'; 
import logo from '../logo.svg'; 
import { Link } from 'react-router-dom'; 
import {connect} from 'react-redux'; 
import * as Actions from '../actions/auth'; 

class Header extends Component { 

constructor() { 
    super(); 
    this.state = { authenticated: false }; 
    } 

    handleSignout() { 
    this.props.signOutUser(); 
    } 

    logOut(event) { 
    event.preventDefault(); 
    this.props.actions.logOutUser(); 
    } 

    render() { 
     if (this.props.authenticated){ 
      return (
       <div> 
        <div className="App"> 
         <div className="App-header"> 
         <img src={logo} className="App-logo" alt="logo" /> 
         <h2>Student Assist App</h2> 
         </div> 
        </div> 
        <div className="navMenu"> 
         <ul> 
          <li><Link to="/">Home</Link></li> 
          <li><Link to="/PhoneNumbers">PhoneNumbers</Link></li> 
          <li><Link to="/Addresses" > Addresses</Link></li> 
          <li><Link to="/Credits" > Credits</Link></li> 

         </ul> 
        </div> 
        <div className="authMenu"> 
         <ul className="list-inline"> 
          {/*<li><img src={profile.picture} height="40px" /></li> 
          <li><span>Welcome, {profile.nickname}</span></li>*/} 
          <Link to="/Home" > logout</Link> 
         </ul> 

        </div> 
       </div> 
      ); 
    }else{ 
      return (
       <div> 
        <div className="App"> 
         <div className="App-header"> 
         <img src={logo} className="App-logo" alt="logo" /> 
         <h2>Student Assist App</h2> 
         </div> 
        </div> 
        <div className="navMenu"> 
         <ul> 
          <li><Link to="/">Home</Link></li> 
          <li><Link to="/PhoneNumbers">PhoneNumbers</Link></li> 
          <li><Link to="/Addresses" > Addresses</Link></li> 
          <li><Link to="/Credits" > Credits</Link></li> 

         </ul> 
        </div> 
        <div className="authMenu"> 
         <ul className="list-inline"> 
          <li><Link to="/SignUp" > Sign Up</Link></li> 
          <li><Link to="/Login" > Login</Link></li> 
         </ul> 
        </div> 
       </div> 
      ); 
    } 

    } 
} 

Header.propTypes = { 
    actions: PropTypes.object.isRequired 
} 

function mapStateToProps(state, ownProps) { 
    return { 
    authenticated: state.authenticated 
    } 
} 

export default connect(mapStateToProps, Actions)(Header); 

标题位于应用程序容器中。

import React, { Component, PropTypes } from 'react'; 
import { ConnectedRouter } from 'react-router-redux'; 
import { connect } from 'react-redux' 
import { history } from '../store/configureStore'; 
import { Route, Redirect } from 'react-router-dom'; 

import Header from '../components/header' 
import Home from '../components/home' 
import Addresses from '../containers/addresses' 
import PhoneNumbers from '../containers/phoneNumbers' 
import NotAuthroised from '../components/notAuthorised' 
import Credits from '../components/credits' 
import LogInPage from '../components/logInPage' 
import LogIn from '../components/logInPage' 
import SignUp from '../containers/signup' 

import '../css/App.css'; 

const PrivateRoute = ({component: Component, authenticated, ...props}) => { 
    return (
     <Route 
      {...props} 
      render={(props) => authenticated === true 
       ? <Component {...props} /> 
       : <Redirect to={{pathname: '/login', state: {from: props.location}}} />} 
     /> 
    ); 
}; 

class App extends Component { 
    constructor(props) { 
    super(props) 
    this.handleLoginClick = this.handleLoginClick.bind(this) 
    this.handleLogoutClick = this.handleLogoutClick.bind(this) 
    } 

    handleLoginClick() { 
    this.props.login() 
    } 

    handleLogoutClick() { 
    this.props.logout() 
    } 

    render() { 
    const { authenticated, profile } = this.props 
    return (
     <ConnectedRouter history={history}> 
     <div> 
      <Header 
      authenticated={authenticated} 
      profile={profile} 
      onLoginClick={this.handleLoginClick} 
      onLogoutClick={this.handleLogoutClick} 
      /> 

      <Route exact={true} path="/" component={Home}/> 
      <Route path="/Home" component={Home}/> 
      <Route path="/PhoneNumbers" component={PhoneNumbers}/> 
      <PrivateRoute authenticated={this.props.authenticated } path="/Addresses" component={Addresses}/> 
      <Route path="/NotAuthroised" component={NotAuthroised}/> 
      <Route path="/Credits" component={Credits}/> 
      <Route path="/Login" component={LogIn}/> 
      <Route path="/SignUp" component={SignUp}/> 


     </div> 
     </ConnectedRouter> 
    ); 
    } 
} 

const mapStateToProps = (state) => { 
    return { authenticated: state.auth.authenticated }; 
}; 

export default connect(mapStateToProps)(App); 

该应用程序容器被index.js

import './index.css'; 

import { Provider } from 'react-redux'; 
import { configureStore } from './store/configureStore' 
import App from './containers/App'; 
import React from 'react'; 
import ReactDOM from 'react-dom'; 
import registerServiceWorker from './registerServiceWorker'; 

const store = configureStore() 
//store.dispatch(loadAddresses()); 


ReactDOM.render(<Provider store={store}> 
        <App /> 
       </Provider>, 
       document.getElementById('root')); 
registerServiceWorker(); 

登录组件正在改变的认证的值称为是

import React, {PropTypes} from 'react'; 
import TextInput from './common/textInput'; 
import {bindActionCreators} from 'redux'; 
import {connect} from 'react-redux'; 
import * as sessionActions from '../actions/auth'; 

class LogInPage extends React.Component { 
    constructor(props) { 
    super(props); 
    this.state = {credentials: {email: '', password: ''}} 
    this.onChange = this.onChange.bind(this); 
    this.onSave = this.onSave.bind(this); 
    } 

    onChange(event) { 
    const field = event.target.name; 
    const credentials = this.state.credentials; 
    credentials[field] = event.target.value; 
    return this.setState({credentials: credentials}); 
    } 

    onSave(event) { 
    event.preventDefault(); 
    this.props.actions.signInUser(this.state.credentials); 
    } 

    render() { 
    return (
     < div> 
     < form> 
      < TextInput 
      name="username" 
      label="Username" 
      value={this.state.credentials.username} 
      onChange={this.onChange}/> 

      < TextInput 
      name="password" 
      label="password" 
      type="password" 
      value={this.state.credentials.password} 
      onChange={this.onChange}/> 

      < input 
      type="submit" 
      className="btn btn-primary" 
      onClick={this.onSave}/> 
     </form> 
     </div> 

); 
    } 
} 

function mapDispatchToProps(dispatch) { 
    return { 
    actions: bindActionCreators(sessionActions, dispatch) 
    }; 
} 
export default connect(null, mapDispatchToProps)(LogInPage); 

的signInUser方法是在动作/ AUTH。 js

import * as types from './actionTypes'; 
import decode from 'jwt-decode'; 
import sessionApi from '../api/authApi'; 

const ID_TOKEN_KEY = 'jwt' 

export function signOutUser() { 
    sessionStorage.removeItem(ID_TOKEN_KEY); 
    return { 
     type: types.SIGN_OUT_USER 
    } 
} 

export function signInUser(credentials) { 
    console.log('singing user is with credentials ' + credentials); 
    return function(dispatch) { 
     return sessionApi.login(credentials).then(response => { 
     sessionStorage.setItem(ID_TOKEN_KEY, response.access_token); 
     dispatch(authUser()); 
     }).catch(error => { 
     console.log('we caught an error ' + error) 
     dispatch(authError(error)); 
     }); 
    }; 
} 

export function isLoggedIn() { 
    return function(dispatch) { 
     const idToken = getIdToken() 
     if (!!idToken && !isTokenExpired(idToken)){ 
      dispatch(authUser()); 
     }else{ 
      console.log('is logged in issue ') 
      dispatch(authError('Not logged in')); 
     } 
    } 
} 

export function getIdToken() { 
    console.log('the token is now ' + sessionStorage.getItem(ID_TOKEN_KEY)); 
    return sessionStorage.getItem(ID_TOKEN_KEY); 
} 

function getTokenExpirationDate(encodedToken) { 
    console.log('in get Exp date with encoded token ' + encodedToken); 
    const token = decode(encodedToken); 
    if (!token.exp) { return null; } 

    const date = new Date(0); 
    date.setUTCSeconds(token.exp); 

    return date; 
} 

function isTokenExpired(token) { 
    console.log('were in isTokenExpired'); 
    const expirationDate = getTokenExpirationDate(token); 
    return expirationDate < new Date(); 
} 

export function authUser() { 
    return { 
     type: types.AUTH_USER 
    } 
} 

export function authError(error) { 
    return { 
     type: types.AUTH_ERROR, 
     payload: error 
    } 
} 

认证减速是

import * as types from '../actions/actionTypes'; 
import initialState from './initialState'; 
//import history from '../history' 

export default function auth(state = initialState, action) { 
    switch (action.type) { 
    case types.AUTH_USER: 
     console.log('we have an auth user request') 
     return { 
     authenticated: true, 
     error : null 
     }; 
    case types.SIGN_OUT_USER: 
    console.log('we have an sign out request') 
     return { 
     authenticated: false, 
     error : null 
     }; 
    case types.AUTH_ERROR: 
    console.log('we have an auth error request') 
     return { 
     error: action.payload.message 
     }; 
    default: 
     return state; 
    } 
} 

,合并的减速是rootReducer

import * as ActionTypes from '../actions/auth' 
import { combineReducers } from 'redux'; 
import { routerReducer } from 'react-router-redux'; 
import { reducer } from 'redux-form'; 
import phoneNumbers from './phoneNumbers'; 
import addresses from './addresses'; 
import auth from './auth'; 

const rootReducer = combineReducers({ 
    auth, 
    addresses, 
    phoneNumbers, 
    routerReducer, 
    reducer 
}); 

export default rootReducer; 

配置商店看起来像

import { isLoggedIn } from '../actions/auth'; 
import {createStore, compose, applyMiddleware} from 'redux'; 
import { routerMiddleware } from 'react-router-redux'; 
import rootReducer from '../reducers/rootReducer'; 
import thunk from 'redux-thunk'; 
import createHistory from 'history/createBrowserHistory'; 
import ReduxPromise from 'redux-promise' 


export const history = createHistory(); 

export function configureStore(initialState) { 
    const store = createStore(
     rootReducer, 
     initialState, 
     compose (
      applyMiddleware(thunk, ReduxPromise, routerMiddleware(history)), 
      window.devToolsExtension ? window.devToolsExtension() : f => f 
     ) 
); 

    if (module.hot) { 
     // Enable Webpack hot module replacement for reducers 
     module.hot.accept('../reducers/rootReducer',() => { 
      const nextRootReducer = require('../reducers/rootReducer').default; 
      store.replaceReducer(nextRootReducer); 
     }); 
    } 

    store.dispatch(isLoggedIn()); 
    return store; 
} 

和initialState.js看起来是这样的。

import { isLoggedIn } from '../actions/auth'; 
import {createStore, compose, applyMiddleware} from 'redux'; 
import { routerMiddleware } from 'react-router-redux'; 
import rootReducer from '../reducers/rootReducer'; 
import thunk from 'redux-thunk'; 
import createHistory from 'history/createBrowserHistory'; 
import ReduxPromise from 'redux-promise' 


export const history = createHistory(); 

export function configureStore(initialState) { 
    const store = createStore(
     rootReducer, 
     initialState, 
     compose (
      applyMiddleware(thunk, ReduxPromise, routerMiddleware(history)), 
      window.devToolsExtension ? window.devToolsExtension() : f => f 
     ) 
); 

    if (module.hot) { 
     // Enable Webpack hot module replacement for reducers 
     module.hot.accept('../reducers/rootReducer',() => { 
      const nextRootReducer = require('../reducers/rootReducer').default; 
      store.replaceReducer(nextRootReducer); 
     }); 
    } 

    store.dispatch(isLoggedIn()); 
    return store; 
} 

对不起所有的代码,但我觉得我经历过这些文件的代码之后,我有不知道为什么它不工作,因为我可以从API获取数据,既当认证是必需的,什么时候不需要。 我假设我犯了一个愚蠢的初学者错误,但如果有人能让我知道那个错误是什么,那将会非常棒。

这是我创建应用程序和我在安装时安装的其他模块的过程。

run create-react-app 
run insatll react-router-dom --save 
run intstall auth0-lock --save 
run install redux --save 
run install redux-thunk --save 
npm install redux-logger --save 
npm install react-redux --save 
npm install [email protected] --save //this needs to be v5 to be compatible with react-router-dom v4 
npm install jwt-decode --save 
npm install redux-promise --save 
npm install history --save 
npm install --save redux-form 

谢谢您的帮助..

+0

问题是什么? 道具不变?道具改变了,但组件不重新渲染?组件根本没有渲染? – Andrew

+0

嘿安德鲁,问题是,我完成登录后,(this.props.authenticated)道具被更改,但标题不会重新呈现。完成登录后,标题应显示“登出”链接,但始终显示登录链接。 –

回答

0

我终于得到了它的工作。 这是问题出在我所在的标题容器中。

function mapStateToProps(state, ownProps) { 
    return { 
    authenticated: state.authenticated 
    } 
} 

功能应该已经

function mapStateToProps(state, ownProps) { 
    return { 
    authenticated: state.auth.authenticated 
    } 
} 

我很想了解其中.auth从state.auth来到... 目前我假设它从AUTH减速的权威性。JS包含此行

export default function auth(state = initialState, action) 

另一个减速器我有PHONENUMBERS有

export default function phoneNumbers(state = initialState.phoneNumbers, action) 

,我可以从state.phoneNumbers访问phoneNumber的。 有人可以证实我的怀疑,或者指向正确的方向吗? 谢谢