2017-08-21 15 views
1

レンダリングコンポーネントは、非同期呼び出しが成功した後にのみ必要です。その前に、ユーザーエクスペリエンスを向上させるためのローディングコンポーネントを示したいと思います。反応コンポーネントの非同期レンダリング、グローバルLoadingコンポーネントの設定方法は?

1つのコンポーネントで、私はそれを扱う方法を知っていて、Reactjs async rendering of componentsを参照しています。しかし私のプロジェクトでは、非同期呼び出しで情報を表示するページ(コンポーネント)が数多くあります。

すべてのコンポーネントに内部状態を書き込むのではなく、グローバルな読み込みコンポーネントをいくつかの場所に設定する方法はありますか?あなたはそのようなこと行うことができますhttps://facebook.github.io/react/docs/higher-order-components.html

function withAsynchronous(WrappedComponent, url) { 
    return class extends React.Component { 
    constructor(props) { 
     super(props); 
     this.state = { 
     isLoading: true 
     }; 
    } 

    componentDidMount() { 
     // You async call 
     GetAsync(url, data => { 
     this.setState({ isLoading: false, data: data }); 
     }); 
    } 

    render() { 
     if (this.state.isLoading) { 
     return (<YourLoadingComponent />); 
     } 

     return <WrappedComponent data={this.state.data} {...this.props} />; 
    } 
    }; 
} 

をし、そのようにそれをレンダリング:

答えて

1

たぶん反応でHOCパターンに見てみましょう

componentDidMount() { 
    const YourAsyncPage = withAsynchronous(
    YourPage, 
    '/your/page/url' 
); 
} 

render() { 
    return (<YourAsyncPage />); 
} 
+0

こんにちは@Paul DSを隠し、私は、HOCsを読みますたくさんのことをたくさん学んだ。私はこれを次のようにしました: 'const MyFund = Loading(WrappedComponent、 'wt/fund/0001.json'); export default MyFund; 'それは動作します(LoadingはHOCです)。 最後の部分について少し混乱しています。「そして、それをレンダリングします。... ...」このパートのコードの使い方は? 'componentDidMount'メソッドと' render'の中で? – jason

+0

私は 'componentDidMount'関数を' YourAsyncPage'オブジェクトの作成方法を示すためだけに使っていましたが、あなたが好きなところで行うことができました。 'render'メソッドでオブジェクトを作成しないよう注意するだけで、各レンダリング時にオブジェクトを再作成しないようにする必要があります –

1

あなたが必要sateの右部分をコンポーネントに委譲する方法です。そのため、アプリケーションにログインコンポーネントがある場合、ログインコンポーネントのハンドラは、それが責任を負う国家の

コンポーネントの読み込みがコンポーネントの状態でloadingの場合と異なる場合は、グローバルユーティリティモジュールの関数を使用してtrueまたはfalseに設定するか、アプリケーションから注入することができます。

アプリケーションのハンドラ(アクションタイプが配列である):

let utils = { 
    toggleLoading:(sate)=> 
    Object.assign(
     {} 
     ,state 
     ,{loading:!state.loading} 
    ) 
} 
switch(action.type.slice[0,1]) { 
    case "login": 
     return Object.assign(
     {} 
     ,applicationState 
     ,{ 
      login: 
      loginHandler(
       applicationState.login 
       ,Object.assign(
       {} 
       ,action 
       ,{type:action.type.slice(1)} 
      ) 
       ,utils 
      ) 
      } 
    ) 
    } 

ログインハンドラ

switch(action.type.slice[0,1]) { 
    case "toggleLoading": 
    return utils.toggleLoading(state) 
} 

コンポーネントは、それが入れ子になっています方法を知らないので、あなたからアクションタイプの配列を渡す必要がありますコンポーネントへの適用、およびコンポーネントからサブコンポーネントへの適用(アクションタイプを状態に追加することができます)。

あなたがロードを表示し、非表示にする一つのコンポーネントを使用したい場合は、コードは、ログインコンポーネントを除いて類似しているがロードコンポーネントには、ログインするアプリケーションの代表者と同じように行動をtoggleLoading委譲します。

ロード・コンポーネントが1つしかないため、ユーティリティ・オブジェクトを渡す必要がないため、ロードの設定方法が重複して実装されることはありません。 API_STARTため

DISPATCHアクションを起動ごとにAPI前に

1

dispatch(apiStart()); 

const apiStart =()=>{ 
    type : "API_START", 
    requestsCOunt : 1 
} 

は、API呼び出しを終えた後、 はAPI_FINSIHのアクションを派遣します。

dispatch(apiFinish()); 

const apiFinish =()=>{ 
    type : "API_FINSIH", 
    requestsCOunt : 1 
} 

レデューサー:状態プロパティstate.requestsCOuntのコンポーネントのチェックで

const uiReducer = (state, action) => { 

    switch (action.type) { 
     case "API_START": 
     return Object.assign({}, state, { 
      requestsCOunt: state.requestsCOunt + 1 
      }); 

    case "API_DONE": 
     return Object.assign({}, state, { 
      requestsCOunt: state.requestsCOunt - 1 
     }); 
    } 
} 

それがstate.requestsCOunt <=0であれば、スピナー

関連する問題