2017-07-02 68 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的。 有人可以證實我的懷疑,或者指向正確的方向嗎? 謝謝

相關問題