2017-12-21 30 views
1

私はReactを初めて使うので、これは初心者の間違いかもしれません。componentDidMountの反応エラー - >マウントされたコンポーネントまたはマウントされているコンポーネントのみを更新できますか?

要約すると、エラー/警告が表示されており、2回フェッチを実行しています。最終的に正しい結果が得られます。

セットアップは、後で追加するプロファイルを変更する機能を備えた、基本的なユーザープロファイル情報を表示するページです。

詳細:

  • componentDidMount

  • 以下にconsole.log出力ごとに、一度呼ばれるように思えるどんな理由であれ、2回呼び出されフェッチ。どちらも、リモートから正しい情報を取得します。

  • this.setState({account.data.data [0]})は、初めて失敗し、エラーをスローします。これは特にとして奇妙で、componentDidMountの中でコンポーネントが呼び出されている間はコンポーネントがマウントされていないことを示唆しています。 fetchおよびsetStateを2回目に実行すると、状態が正しく更新されます。

正確なエラーメッセージ:

警告:のみ搭載または取り付けコンポーネントを更新することができます。これは通常、マウントされていないコンポーネントに対してsetState、replaceState、またはforceUpdateを呼び出したことを意味します。これはノーオペレーションです。

これは主成分である:

class AccountTable extends React.Component{ 

constructor(props){ 
    super(props) 
    this.state={ 
     account:{}, 
    } 
} 

componentDidMount(){ 
    console.log('componentDidMount');//outputs once 
    fetch('/mon-compte-api', { 
     method: 'get', 
     credentials: 'same-origin' 
    }) 
    .then((response) => { 
     console.log('fetch'); // outputs twice 
     response.json().then((data) => { 
      console.log('data', data);// correct output both times 
      this.setState({account: data.data[0]}) // this throws the error 
      console.log('state_account', this.state.account); 
// no output for this.state.account first time around. Correct output 2nd time 
     })  
    }) 
    .catch((err) => { 
     console.log(err) 
    });  
} 

render(){ 
    return (
     <table> 
       <TableRow 
        account={this.state.account} /> 
     </table> 
    );  
} 
} 

ReactDOM.render(<AccountTable />,document.querySelector("#react_account")); 

これは、子コンポーネントである:要求された

const TableRow = (props) => { 
if(Object.keys(props.account).length === 0){ //show something while awaiting fetch 
    return (
     <tbody> 
      <tr><td>Loading.....</td></tr> // shows momentarily 
     </tbody> 
     ); 
}else{ 
     return (// outputs correct info eventually 
      <tbody> 
       <tr><th>Name</th><td>{props.account.name}</td></tr> 
       <tr><th>Email</th><td>{props.account.email}</td></tr> 
      </tbody> 
     ); 
} 
} 

応答情報:

Status code: 200 OK 
Date: Thu, 21 Dec 2017 11:53:50 GMT 
Server: Apache/2.2.32 (Unix) mod_wsgi/3.5 Python/2.7.13 PHP/7.1.8  mod_ssl/2.2.32 OpenSSL/1.0.2j DAV/2 mod_fastcgi/2.4.6 mod_perl/2.0.9 Perl/v5.24.0 
X-Powered-By: PHP/7.1.8 
Cache-Control: no-cache, private 
Content-Length: 600 
Keep-Alive: timeout=5, max=99 
Connection: Keep-Alive 
Content-Type: application/json 
+0

私は問題はAccountTableの親内にあると思いますが、あなたはここにコードを投稿することができますか? –

+0

完全な 'response'ステータスコードとヘッダーを記録すると、認証方法と関係があるかもしれません。たぶん、認証を求める最初の呼び出しで401を受け取った後、フェッチが資格情報で2番目の呼び出しを行う場合があります。フェッチのドキュメントを見つけることができませんでしたが、要求モジュールでよく説明されています:https://github.com/request/request#http-authentication –

+0

@GabrielBleu、ありがとう。上記の回答情報を追加しました。 200 OKです。 – BernardA

答えて

0

コンポーネントの状態でisMountedを試してみてください。コンポーネントがマウントされているか、マウントされているかを確認してから、setState()を実行する必要があります。

コンポーネントのレンダリングライフサイクルに非同期操作が存在するため、機能setState()を使用する方が良いでしょう。

isMounted状態を初期設定でtrueと設定します。

constructor(props){ 
    super(props) 
    this.state={ 
     isMounted: true 
     account:{}, 
    } 
} 

その後、falseときcomponentWillUnmount()実行にthis.state.isMountedを変更します。その後、

componentWillUnmount(){ 
    this.setState({ 
    isMounted: false 
    }) 
} 

this.setState({account: data.data[0]})を行う前に、機能setState()this.state.isMountedをチェックアウト:

.then((response) => { 
     console.log('fetch'); // outputs twice 
     response.json().then((data) => { 
      console.log('data', data);// correct output both times 
      this.setState(function (state, props) { // Functional setState 
       if(state.isMounted){ 
         return { 
          account: data.data[0] 
         } 
       } 
      }); 
      console.log('state_account', this.state.account); 
      // no output for this.state.account first time around. Correct output 2nd time 
     })  
}) 
+0

ありがとう、しかし、それはそれを解決するように見えませんでした。 isMountedは実際に初期設定に影響を与えないので意味があります。ここでも、コードはcomponentDidMount内で実行されています。コンポーネントは定義によってマウントする必要があります。 – BernardA

+0

コンポーネントをマウントする必要はありません。非同期関数 'fetch()。then(...)'を呼び出しているので、 'then()'メソッドが呼び出しているときにアンマウントされるかもしれないからです。あなたが私を許せば私は私の答えを取り除かないでしょう。多分この回答は他人を助けます。 –

関連する問題

 関連する問題