2016-08-16 37 views
1

私はReact/Reduxを学んでいるところですが、私の単一ページのWebアプリケーションをフレームワーク/パラダイムに変換する際に問題に遭遇しました。私がしようとしているのは、Webアプリケーションの初期状態に、APIリクエストのオブジェクトによって設定される配列があるということです。この配列は「作成」と呼ばれます。私はこれをやりたいので、ウェブサイトの最初のページにAPIからの「作成」を表示することができます。React/Reduxは状態の配列を反復できません

import App from './App'; 
import './index.css'; 
import configureStore from './redux/store' 
import { Provider } from 'react-redux' 

let makesUrl = 'the url to the API' 
let cached = cache.get(makesUrl) 
let makes = [] 

// Future cache setup. 
if(!cached) { 
    console.log("NOT CACHED") 
} 
else { 
    console.log("CACHED") 
} 

// Get the makes via API. 
fetch(makesUrl).then((response) => { 
    // Pass JSON to the next 'then' 
    return response.json() 
}).then((json) => { 
    json.makes.forEach((make) => { 
     makes.push(make) 
    }) 
}) 

let initialState = { 
    grids: [], 
    makes: makes 
} 

let store = configureStore(initialState) 

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

statedispatch小道具にマッピングされ、そのように私のApp.jsファイルでそれらを必要とするコンポーネントに渡されます:で

import React, { Component } from 'react' 
import { connect } from 'react-redux' 
import { bindActionCreators } from 'redux' 
import './App.css' 
import Head from './components/Head' 
import Middle from './components/Middle' 
import Foot from './components/Foot' 
import actions from './redux/actions' 

class App extends Component { 

    render() { 
    return (
     <div className="App"> 
     <div> 
      <Head /> 
      <div className="middle container"> 
      <Middle actions={this.props.actions} makes={this.props.makes}/> 
      </div> 
      <Foot /> 
     </div> 
     </div> 
    ); 
    } 
} 

function mapStateToProps(state) { 
    return state 
} 

function mapDispatchToProps(dispatch) { 
    return { 
    actions: bindActionCreators(actions, dispatch) 
    } 
} 

export default connect(mapStateToProps, mapDispatchToProps)(App) 

これは、以下のindex.jsファイルで見ることができますすべてのポイント、クロム開発ツールでは、私は、API呼び出しが成功し、状態が62オブジェクトを持つmakes: Array[62]が表示されていることがわかりますが、これらのことが行われるコンポーネントの配列の長さをログコンソール以下に示すように、長さは0であると言います配列の各インデックスは定義されていません。

import React, { Component } from 'react' 

    class MakeButtons extends Component { 

     handleClick(event) { 
      event.preventDefault() 
      console.log("CLICK") 
     } 

     render() { 
      return(
       <div> 
        { 
         console.log(this.props.makes.length) 
        } 
       </div> 
      ) 
     } 
    } 

    export default MakeButtons 

これは私が過去数時間のために把握しようとしてきたものを、本質的であるので、私はしかしでは、アレイ内の各オブジェクトのリンク/ボタンを返すようにforEachまたはmap機能を使用することができます状態が正常であることを示す開発ツールにもかかわらず、これが機能しない瞬間です。どんな助けや説明も大歓迎です!

+1

あなたのinit関数を呼び出します。だからあなたのコンテナは、次のようになります。さらに、initコールをアクション/レデューサーにして、このプロセスをもっとクリーンにし、アプリケーションが最初のフェッチ呼び出しに基づいてハングする必要がないようにする必要があります。 – ajmajmajma

+0

@ajmajmajmaああ、意味があります!この状況でアクションをディスパッチするには、componentWillMountメソッドが適切でしょうか? – sidp

+0

はい、アプリケーションの読み込み時に一度だけ呼び出されるため、componentWillMountまたはcomponentDidMountです。非同期呼び出しを使用して状態を更新し、それらの状態の1つで呼び出すアクションを作成します。 – ajmajmajma

答えて

1

あなたのinitのアクション/レデューサーを設定するだけでよいので、アプリケーションをロードするときに一度だけ呼び出されるので、componentWillMountまたはcomponentDidMountで呼び出すことができます。

フェッチのデータを使用するフェッチとアプリがあるので、ではなく、で、アプリケーションを開始する前に非同期コールが終了するのを待っています。

あなたは自分の行動の作成者は、のようなものになるだろうので、あなたのinitアクションを作成したい

import * as services from './services'; 

    function initMyAppDispatcher(type, data, status) { 
     return { 
      type, 
      data, 
      status 
     }; 
    } 


    export function initMyApp(dispatch, makesUrl) { 
     dispatch(initMyAppDispatcher(actions.INIT_APP, {}, 'PENDING'); 

     return services.myInitCall(makesUrl) 
     .then((data) => 
      dispatch(initMyAppDispatcher(actions.INIT_APP, data, 'SUCCESS'), 
      (error) => 
      dispatch(initMyAppDispatcher(actions.INIT_APP, error, 'FAILURE'), 
     ) 
     .catch(yourErrorHandling); 
    } 

Services.myInitCallは、あなたがちょうどあなたが約束通り戻ってそれをエクスポートすることを確認し、それを実装したいがあります。あなたの場合は、そこにアクセスできる限り、その行をfetch(makesUrl)に置き換えることができます。そして、それはこのように設定持つ、あなたがそうのようなあなたのレデューサーを設定することができます。注意すべき

case actions.INIT_APP: 
      if (action.status) { 
       switch (action.status) { 
        case PENDING: 
         //you can use this to create a "loading" state like a spinner or whatever 
         return state; 
        case SUCCESS: 
         // note: this is immutablejs syntax, use whatever you prefer 
         return state.set('makes', action.data); 
        case FAILURE: 
         return state; 

        default: 
         return state; 
       } 
      } 
      return state; 

ことの一つは、私がmapToPropsの代わりにmapDispatchToPropsを使用するので、私は自分の行動のクリエイターでの発送を持っています。フェッチが帰ってきた前に、あなたはあなたのアプリケーションを初期化している、あなたのコンポーネントcomponentWillMountcomponentDidMountで、渡す

import * as actionCreators from './action-creators'; 

function mapStateToProps(state) { 

    return { 
     makes: state.get('makes') 
    }; 
} 

function mapDispatchToProps(dispatch, ownProps) { 
    return { 
     initMyApp: actionCreators.initMyApp.bind(null, dispatch) 
    }; 
} 


export default function(component = Component) { 
    return connect(mapStateToProps, mapDispatchToProps)(component); 
} 

componentDidMount() { 
     this.props.initMyApp(); 

    } 
+0

これは素晴らしい説明です、ありがとうございます! – sidp

関連する問題