2016-11-29 4 views
0

ReactとReduxでタイマーを作成しようとしています。ReactJS:Uncaught TypeError:未定義(...)のプロパティ 'subscribe'を読み取ることができません。

私は可能な限り懸念事項を分けています。私は実際の解決策を見つけるのを助けてください!ありがとうございました。

エラー:キャッチされない例外TypeError:プロパティを読んで、未定義の '購読' することはできません(...)

タイマーコンポーネント

Timer.js 

import React, { Component } from 'react'; 
import timer from '../reducers/index.js'; 
import store from '../stores/timerStore.js'; 


// React Component to display the timer 
class Timer extends Component { 
    constructor() { 
    super(); 
    this.start = this.start.bind(this); 
    this.stop = this.stop.bind(this); 
    } 

    start() { 
     store.dispatch({ 
     type: 'START_TIMER', 
     offset: Date.now(), 
    }); 
    } 
    stop() { 
    store.dispatch({ 
    type: 'STOP_TIMER' 
    }); 
} 
format(time) { 
    const pad = (time, length) => { 
    while (time.length < length) { 
    time = '0' + time; 
    } 
    return time; 
} 

time = new Date(time); 
let m = pad(time.getMinutes().toString(), 2); 
let s = pad(time.getSeconds().toString(), 2); 
let ms = pad(time.getMilliseconds().toString(), 3); 

return `${m} : ${s} . ${ms}`; 
} 

render() { 
    return (
    <div> 
     <h1>Time: {this.format(this.props.time)}</h1> 
     <button onClick={this.props.isOn ? this.stop : this.start}> 
     { this.props.isOn ? 'Stop' : 'Start' } 
     </button> 
    </div> 
    ); 
    } 
} 



export default Timer; 

タイマーリデューサー

timer.js 

    // Initial state for reducer 
    const initialState = { 
     isOn: false, 
     time: 0 
    }; 


    function timer(state = initialState, action) { 
     switch (action.type) { 
      case 'START_TIMER': 
      return { 
      ...initialState, 
      isOn: true, 
      offset: action.offset, 
      }; 

      case 'STOP_TIMER': 
      return { 
      isOn: false, 
      time: state.time 
      }; 

     case 'TICK': 
      return { 
      ...state, 
      time: state.time + (action.time - state.offset), 
      offset: action.time 
      }; 

     default: 
     return state; 
     } 
    } 

    export default timer; 

タイマーストア

timerStore.js 

    import { createStore } from 'redux'; 
    import timer from '../reducers/index.js'; 

    // Create store using the reducer 
    export const store = createStore(timer); 

メインアプリケーションコンポーネント次の2つの異なる問題持っている

index.js 

    import React, { Component } from 'react'; 
    import ReactDOM from 'react-dom'; 
    import Timer from './components/Timer.js'; 
    import store from './stores/timerStore.js'; 

    const render =() => { 
     ReactDOM.render(
     <Timer 
      time={store.getState().time} 
      isOn={store.getState().isOn} 
      interval={store.getState().interval} 
     />, 
     document.getElementById("app") 
    ); 
    } 

    store.subscribe(render); 

    var interval = null; 
    store.subscribe(() => { 
     if (store.getState().isOn && interval === null) { 
      interval = setInterval(() => { 
      store.dispatch({ 
     type: 'TICK', 
     time: Date.now() 
     }); 
    }); 
    } 
    if (!store.getState().isOn && interval !== null) { 
     clearInterval(interval); 
     interval = null; 
    } 
    }); 

    render(); 
+0

エラーと一緒にファイルと行番号を取得しましたか? –

答えて

1

まず、あなたは店の変数の「名前の輸出」が、そのファイルの「デフォルトのインポート」をやっています。あなたは2つが一致することを確認する必要があります。 export default createStore(timer)import store from "./stores/timerStore"、またはexport const store = createStore(timer)import {store} from "./stores/timerStore"のいずれかを実行します。

第2に、実際に店舗の「手動」購読を行ってはいけません。 React-Reduxパッケージにはconnectという機能があり、サブスクリプションと更新プロセスを管理するコンテナコンポーネントが生成されます。

"stores"という名前のフォルダは、複数のReduxストアを作成していることを示唆しています。 ですが、推奨する方法ではありません。

更新

そして、それを見て、あなたは第三の問題持っている:それはストアが更新されました知らないので、<Timer>コンポーネントが再表示されませんが。 ReactDOM.render(<Timer>)呼び出しの初期値のみを使用します。

私はちょうど以下に書いたが、あなたは実際にはいくつかの異なるコンポーネントとしてこれを書く必要があります。 1つのコンポーネントをReduxストアに接続し、タイマロジックをsetIntervalで管理し、タイマ情報を表示する別のコンポーネントをレンダリングする必要があります。

+0

+1最初の点に目を向ける。タイマーを管理するサブスクリプションでは、DOMコンポーネントの一部として存在しないため、サブスクライブを直接使用すると意味があります。 –

+0

実際、それはカップルの "コンテナ"コンポーネントのための大きな用途のようです。 'connect'呼び出しは、Reduxストアにアクセスする1つのコンテナを生成し、' connect'に渡されたコンポーネントはそれ自体、間隔を管理し、 ''をレンダリングする「コンテナ」タイプのコンポーネントです。 – markerikson

+0

更新が間違っています。それは再レンダリングされます。レンダー機能は、状態が変化するたびに呼び出され、状態項目の現在の値をフェッチします。 –

関連する問題