2016-12-09 5 views
0

私はreactjsの状態に関するいくつかの困難に直面しています。 私が知る限り、componentWillMountは、コンポーネントがレンダリングされる前にajax呼び出しでデータをロードする場所です。 私は、積み重ねられたデータをパネルに積み重ねて、それをボード上に表示するシンプルなプロジェクトを持っています。しかし、ajax呼び出しからのデータは、コンポーネントのレンダリングの前に設定されず、空の配列を持つボードのレンダリングにつながります。 follwoingは私の完全なソースです:問題の根本であるcomponentWillMountはレンダリングの前に終了しません

import React from "react"; 
export class Panel extends React.Component{ 
render() { 
    return (
    <div> 
     <div className="row panel"> 
      <div className="col-sm-12 header">sfsfsf</div> 
      <div className="col-sm-12 body">fsdfsfs</div> 
      <div className="col-sm-12 footer">fasfaf</div> 
     </div> 
    </div> 
    ); 
    } 
    } 

と理事会のクラスは次のようにされています。また、最後のクラスはindex.jsある

import React from "react"; 
import {Panel} from "./Panel"; 
export class Board extends React.Component{ 
constructor(props){ 
    super(); 
    this.state={news: []}; 
} 
componentWillMount(){ 
    this.state={news: []}; 
    $.ajax({ 
     url: "http://localhost:3003/json.txt", 
     dataType: 'json', 
     cache: false, 
     success: function(data) { 
      var arr=[]; 
      for (var key in data) { 
       arr.push(data[key]); 
       console.log(data[key]); 
      } 
      this.state={news: arr}; 
     }}); 
    } 
    render() { 
    return (
     <div> 
      { 
       this.state.news.map((item,i)=> <Panel key="i"/>) 
      } 
     </div> 
    ); 
    } 
} 

import React from "react"; 
import {render} from "react-dom"; 
import {Board} from "./component/Board"; 

class App extends React.Component{ 

    render(){ 
    return(
     <div> 

      <Board/> 

     </div> 

    ); 
    } 

} 

render(<App/>, document.getElementById('middle')); 

Board.jsクラスで見ることができるように、レンダリング関数で配列を初期化してから、componentWillMountを使用してnewsWillMountを使用して、componentWillMountが終了した後に起こることを期待していますが、レンダリングが発生すると、配列は空です。何か案が?

********* UPDATE ***************

私もcomponentDidMountでそれを試してみましたが、それはうまくいきませんでしたし、同じ問題

+0

あなたが記述しているのは、非同期関数を呼び出すと予想される結果です。どこから呼び出しても、リアクションのライフサイクルはサーバーのコールバックを待つことなくレンダリングされます。同期呼び出し(それほどうまくいきません)か、AJAX呼び出しの1つのコンポーネントを呼び出して、結果をあなたの 'Board 'にpropsとして渡してください。 –

答えて

1

componentWillMount()がレンダリング前に終了していますが、ajaxが非同期であるため、要求が完了するまで実行されません。

this.state = ...を使用して状態を設定しないでください。代わりに、次の値を使用します。

this.setState({news: arr}); 

これは値を設定し、コンポーネントとすべての子をレンダリングさせます。 nullデータをうまく処理するためにレンダリング関数を書くだけで、JS実行をブロックすることなく期待どおりの結果を得ることができます。

ここで示唆したように、それは適切な結合である:

import React from "react"; 
import {Panel} from "./Panel"; 
export class Board extends React.Component{ 
    constructor(props){ 
    super(); 
    } 

    getInitialState() { 
    return {news: []}; 
    } 

    componentWillMount(){ 
    $.ajax({ 
     url: "http://localhost:3003/json.txt", 
     dataType: 'json', 
     cache: false, 
     success: (data) => { 
     var arr=[]; 
     for (var key in data) { 
      arr.push(data[key]); 
      console.log(data[key]); 
     } 
     this.setState({news: arr}); 
     } 
    }); 
    } 
    render() { 
    return (
     <div> 
      { 
       this.state.news.map((item,i)=> <Panel key="i"/>) 
      } 
     </div> 
    ); 
    } 
} 

矢印機能は、バインディングを処理します。同様にfunction(){}.bind(this)

+0

'this.state'の良いキャッチ。また、成功コールバックの無名関数に 'this.state'があることに気付きました。 'this'はあなたが期待するものではない可能性が最も高いので、別の方法で州にアクセスする必要があります。 –

+0

@Sandwichz良いキャッチ。私は矢の機能を使うのに慣れているので、しばしばバインドすることは私の心をスキップします。私は私の例を更新します。 –

+0

ありがとうございます。ここで.bind()の役割を説明してください。 –

1

あなたはasyncであるajax呼び出しを行っています...定義により、ajaxの応答を待たずにコードを実行し続けます。

これを同期させるには、$ .ajaxオプションでasync:falseを設定します。

関連する問題