2016-11-10 28 views
0

私は反応を覚えており、このチュートリアルに従う:https://scotch.io/tutorials/build-a-react-flux-app-with-user-authentication私のアプリケーションに認証を追加する。状態が変更された後に反応コンポーネントが再レンダリングされない

悲しいことに、私はログインボタンを更新するだけで、認証されたコンテンツを見るためにブラウザをリフレッシュする必要があることに気付きました。

私はすべての上に検索し、無駄に状態や小道具を設定し、子供たちに親からそれらを渡すが、すべて試してみました。

以下は私の3つのコンポーネントです。何でも大歓迎です。ウェブ全体を見てきました。&は、他のリアクト・アプリケーションを既に研究しています。

ありがとうございました。

App.js

import 'normalize.css/normalize.css'; 
import 'bootstrap/dist/css/bootstrap.min.css'; 

import React, { Component } from 'react'; 
import PlayButton from './PlayButton'; 
import SlotMachine from './SlotMachine'; 

import AuthActions from '../actions/AuthActions'; 
import AuthStore from '../stores/AuthStore'; 



class AppComponent extends Component { 



    componentWillMount() { 
     this.lock = new Auth0Lock('3RhBq3qZaZARDQae7PtbH59wyP9xe7Ld', 'wolftiger.eu.auth0.com'); 
    } 

    constructor(props) { 
     super(props); 
     this.state = { 
      authenticated: AuthStore.isAuthenticated() 
     } 
    } 


    login() { 
     // We can call the show method from Auth0Lock, 
     // which is passed down as a prop, to allow 
     // the user to log in 
     //console.log("parent login", this.props); 
     this.props.lock.show((err,profile,token) => { 
      if (err) { 
       alert(err); 
       //console.log(err); 
       return; 

      } 
      AuthActions.logUserIn(profile, token); 
      //this.props.login(); 
      this.setState({authenticated:true}); 
     }); 
    } 

    logout() { 
     AuthActions.logUserOut(); 
     //this.props.logout(); 
     this.setState({authenticated:false}); 
    } 

    render() { 
     console.log(this, this.props, this.props.children, this.state); 
     return (
      <div> 
      <div className="container"> 
       <div className="row"> 
        <div className="medium-12 small-12"> 
         <h1>Spin and Win</h1> 

         { !this.state.authenticated ? (
         <div className="medium-12 small-12"> 
          <img src="http://placehold.it/960x360"/> 
         </div> 
         ) : (
          <SlotMachine state={this.state} props={this.props} > 
          </SlotMachine> 
         )} 
        </div> 
       </div> 
       <div className="row"> 
        <div className="medium-12 small-12"> 
         <PlayButton 
          lock={this.lock} 
          state={this.state} 
          login={this.login} 
          logout={this.logout} 
         > 
         </PlayButton> 
        </div> 
       </div> 
      </div> 
      </div> 
     ); 
    } 
} 

//AppComponent.defaultProps = {}; 


export default AppComponent; 

SlotMachine.js

'use strict'; 

import React   from 'react'; 
import Slots   from './Slots'; 
import SpinButton  from './SpinButton'; 
import StatusMessage from './StatusMessage'; 
import Chances from './Chances'; 

const propTypes = { 
    currentUser: React.PropTypes.object 
}; 


// The SlotMachine React class handles the entirety of this very small app. 
class SlotMachine extends React.Component { 

    constructor(props) { 
    super(props); 
    this.state = { 
     slotPositions: this.getRandomState(), 
     chancesLeft: 3//this value must be stored in the db 

    }; 
    //console.log(this.state.slotPositions); 
    } 

    // Generates random initial state for slots. 
    componentWillMount() { 

    } 



    //getInitialState() { 
    // return {slotPositions: this.getRandomState()}; 
    //} 

    genSlotValue(){ 
    return Math.floor(Math.random() * 3); 
    } 

    // Generates random landing values for slots using genSlotValue defined at the end of the file 
    getRandomState() { 
    //console.log(genSlotValue(), genSlotValue(), genSlotValue()); 
    return [ 
     genSlotValue(), 
     genSlotValue(), 
     genSlotValue() 
    ]; 
    } 

    useChance() { 
     var noOfChances = this.state.chancesLeft; 
     this.setState({chancesLeft: minusOne(noOfChances)}) 
    } 

    componentWillReceiveProps() { 
    //console.log('componentWillReceiveProps'); 
    //ReactDOM.render(newProps); 
    } 

    handleButtonClick(event) { 
    //console.log(event, this, this.state); 
    this.useChance(); 
    console.log(event, this, this.state, this.props); 
    event.preventDefault(); 
    // Set count to 0 before each button press 
    let count = 0; 
    // Set a random state as the final state of all slots before we start spinning 
    let finalState = this.getRandomState(); 
    // Make sure we start with a fresh state for all slots on each spin 
    let currentState = this.getRandomState(); 
    //console.log(currentState,finalState) 
    // Spinning happens here 
    var makeSpin = function(){ 
     let nextState = currentState; 
     let hasChanged = false; 
     var spinButton = document.getElementById('spin-button'); 

     // Evaluate whether or not slots are on their final destination, spin to nextState if not 
     for(var i = 0; i < 3; i++){ 
     if (count < 9 || currentState[i] != finalState[i]) { 

      nextState[i] = (currentState[i]+1)%3; 
      hasChanged = true; 
      spinButton.setAttribute('disabled', 'disabled'); 
      //spinButton.setTextContent('Spinning!'); 
      spinButton.classList.add('spinning'); 
     } 
     //Re-enable spin button 
     if (count >= 9){ 
      //console.log('count more than 9') 
      spinButton.removeAttribute('disabled'); 
      // spinButton.setTextContent('Spin!'); 
      spinButton.classList.remove('spinning'); 
     } 
     } 

     // Moves reel to the next assigned state if it's not yet on it's final value. 
     this.setState({slotPositions: nextState, isFinal: !hasChanged}) 

     // Stops reel spinning if we've hit the final state's value 
     if(!hasChanged) { 
     return; 
     } 
     currentState = this.state.slotPositions; 
     setTimeout(makeSpin, 100); 
     count++; 
     //console.log(count); 
    }.bind(this); 


    // Actually spin 
    makeSpin(); 
    } 




    render() { 

     // Define winning states 
     let sp = this.state.slotPositions; 
     let isWinning = (sp[0] == sp[1]) && (sp[1] == sp[2]); 

     // Make sure winner, winnerClass, and winnerImage strings are undefined until there's an actual win 
     let winner = ''; 
     let winnerClass = ''; 
     let winnerImage = ''; 

     // Make sure we're only displaying the win state on final slot positions 
     if(isWinning && this.state.isFinal){ 
     winner = [ 
      <h2>You've won John Lewis vouchers!</h2>, 
      <h2>You've won M&amp;S vouchers!</h2>, 
      <h2>You've won Size vouchers!!</h2> 
     ][sp[0]]; 
     winnerClass = [ 
      'coffee', 
      'tea', 
      'espresso' 
     ][sp[0]]; 
     winnerImage = [ 
      <div id='coffee-img' className='tossing win-img'></div>, 
      <div id='tea-img' className='tossing win-img'></div>, 
      <div id='espresso-img' className='tossing win-img'></div> 
     ][sp[0]]; 
    } 

    //console.log(this, this.props, this.props.state.authenticated); 
    return (
     <main className='react-slots'> 
     <div className="medium-12 small-12"> 
      <Chances chancesLeft={this.state.chancesLeft} /> 
      <section className="machine"> 
      <Slots slotPositions={this.state.slotPositions} /> 
      <div className="spin row"> 
       <SpinButton onButtonClick={this.handleButtonClick.bind(this)} /> 
      </div> 
      </section> 
      <section className="win row"> 
      <StatusMessage winner={winner} winnerClass={winnerClass} winnerImage={winnerImage} /> 
      </section> 
     </div> 
     </main> 
    ); 
    } 

} 

// Generates a random slot value. 
function genSlotValue(){ 
    return Math.floor(Math.random() * 3); 
} 

function minusOne(value){ 
    return value - 1; 
} 



SlotMachine.propTypes = propTypes; 


export default SlotMachine; 

PlayButton.js

'use strict'; 

import React, {Component} from 'react'; 
import AuthStore from '../stores/AuthStore'; 

// Creates Spin Button 
class PlayButton extends Component { 

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

    render() { 
     //console.log(this, this.props, this.state.authenticated); 
     return (
      <div> 
      {!this.state.authenticated ? (
       <div className="medium-4 small-12"> 
        <button id="play-button" className="play-button" onClick={this.props.login.bind(this)}>Play!</button> 
       </div> 
      ) : (
       <div className="medium-4 small-12"> 
        <button id="play-button" className="play-button" onClick={this.props.logout.bind(this)}>Log out!</button> 
       </div> 
      )} 
      </div> 
     ); 
    } 

} 

export default PlayButton; 

答えて

0

まず第一に、あなたはAuthStoreAuthActionsをインポートされていません。また、lockは小道具としてAppComponentに渡されます。 this.props.lockを実行する前に、小道具でロックを使用できることを確認する必要があります。コードを別のファイルに再構成することができれば、何が起きているのかを簡単に把握することができます。あなたが含まれている必要がありますが、おそらくthis.props.lock.show

+0

お返事ありがとうございます。私のコードは別のファイルにありますが、ここにすべて貼り付けて、何が起きているのかを確認することができます。認証は機能していますが、すべてのコンポーネントで状態を設定してレンダリングする必要があります。現在、ログインボタン自体は認証状態で再レンダリングされます。残りの部分は、リフレッシュ時にのみ認証されます。あなたは、コードを分割するためにあなたに別のファイルと輸入 –

+0

を助け場合、私はあなたのプロジェクトを表示することができます。認証された状態でどのコンポーネントを再レンダリングするか、認証されたときと認証されなかったときの違いは何ですか?コードからは、アプリケーションを見ると、ボタンだけが –

+0

さて、感謝を示すために、私は上記のコードを分割しました –

0

するのではなく、あなたのloginメソッド内this.lock.showを行う必要があり、あなた自身の場合には、チュートリアルから、this.lockHeaderコンポーネントに小道具として渡された、その後this.props.lock.showは、ヘッダーコンポーネントで呼ばれていました後者は子要素/要素が内部にあると仮定しているため<SlotMachine state={this.state} props={this.props} ></SlotMachine>の代わりにSlotMachineのように<SlotMachine state={this.state} props={this.props} />のようになります。また、おそらくそれに渡す小道具の名前を変更する必要があります。 this.props.props

+0

私はそれを試みましたが、何の違いもなく、コンポーネントが再レンダリングされていない、多分componentWillReceiveの小道具を使用する必要がありますとsetState? setStateは、コンポーネントの再レンダリングをトリガするはずです –

0

私はこの問題を解決するためにreact-routerを設定し、新しいコンポーネントをロードすることで、新しくロードされたコンポーネントが認証をチェックし、適切なコンテンツを表示するようにしました。

私のアプリは実際にはページに埋め込まれているのでルーティングは必要ありませんが、ルーティングなしで解決策を見つけたいと思いますが、今のところ十分です。

関連する問題