2017-07-02 6 views
1

私は反応を覚えようとしていますが、私は認証された小道具をセットしたときにヘッダーコンポーネントを再レンダリングすることに固執しています。私はそれについて多くのことを読んでいましたが、それほど多くの異なるコーディングスタイルがあり、私はそれらを効果的に実装することができないようです。 this.props.authenticatedが変更されたときに再レンダリングするようにしています。これは私の最新の試みですが、私はそれをコードの小さな部分で動作させることはできませんでしたので、ブロック全体をやると思いました。私のコントローラの1つがレンダリングされません。

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方法は、アクション/認証です。 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; 

のconfigureストアが

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

機能は、私は.authはstate.authでどこから来たのか理解するのが大好きだ

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

されている必要があります... 現在、私はそれが認証減速払いからだと仮定しています。電話番号のために私が持っている別の減速が

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

を持っていると私はstate.phoneNumbersからにphoneNumberにアクセスすることができ、このラインに

export default function auth(state = initialState, action) 

が含まれていJS。 誰かが私の疑惑を確認することができますか、あるいは正しい方向に私を指差しているのは素晴らしいことでしょうか? ありがとうございます

関連する問題