2017-08-25 7 views
0

MobXで反応する(create-react-appから)。非同期バックエンドAPI呼び出しにAxiosを使用する。リファクタリングによって初期状態が破損する

このコードは機能します。初期状態(問題の配列)が入力され、このコンポーネントを提示するWebページは状態からの初期コンテンツをレンダリングします。

import { observable, computed, autorun, reaction } from 'mobx' 
import axios from 'axios' 

class IssuesStore { 
    @observable issues = [] 

    constructor() { 
    autorun(() => console.log("Autorun:" + this.buildIssues)) 

    reaction(
    () => this.issues, 
     issues => console.log("Reaction: " + issues.join(", ")) 
    ) 
    } 

    getIssues(data) { 
    return data.map((issue) => ({title: issue.name, url: issue.url, labels: issue.labels})) 
    } 

    @computed get buildIssues() { 
    const authToken = 'token ' + process.env.REACT_APP_GH_OAUTH_TOKEN 

    axios.get(`https://api.github.com/repos/${process.env.REACT_APP_GH_USER}/gh-issues-app/issues`, 
        { 'headers': {'Authorization': authToken} }) 
     .then(response => { 
     console.log(response) 
     this.issues = this.getIssues(response.data) 
     return this.issues 
     }) 
     .catch(function(response) { 
     console.log(response) 
     }) 
    } 
} 

export default IssuesStore 

は、個々のコンポーネントや店舗からのAPI呼び出し約束を分離する試みで、私は、関数の集合として、別のJSファイルにaxiosコールを引き抜い:

import axios from 'axios' 

const authToken = 'token ' + process.env.REACT_APP_GH_OAUTH_TOKEN 

export function loadIssues() { 
    return this.apiPromise(
    `https://api.github.com/repos/${process.env.REACT_APP_GH_USER}/gh-issues-app/issues`, 
    { 'headers': {'Authorization': authToken} } 
) 
} 

export function apiPromise(endpoint, options) { 
    return axios.get(endpoint, options) 
     .then((response) => { 
     // console.log("response: " + JSON.stringify(response, null, 2)) 
     return response.data.map((issue) => ({title: issue.name, url: issue.url, labels: issue.labels})) 
     }) 
     .catch(function(response) { 
     console.log(response) 
     }) 
} 

、私の店を次のようになります。

import { observable, computed, autorun, reaction } from 'mobx' 
import * as github from '../api/github' 

class IssuesStore { 
    @observable issues = [] 


    constructor() { 
    autorun(() => console.log("Autorun:" + this.buildIssues)) 

    reaction(
    () => this.issues, 
     issues => console.log("Reaction: " + issues.join(", ")) 
    ) 
    } 

    @computed get buildIssues() { 
    this.issues = github.loadIssues().data 
    return this.issues 
    } 
} 

export default IssuesStore 

はるかに小さい...しかし、それは今としてissuesの初期状態を見ているので、Webページは現在エラーがスローされます最初のレンダリングでは0です。

Uncaught TypeError: Cannot read property 'map' of undefined

約束は、後に(それが必要として)正常に完了したが、その後で、それは遅すぎます。確かに、レンダリングコンポーネントで、.mapなどの空の関数や未定義の変数を実行しないように設定することができます。

しかし、なぜコードはリファクタリングの前ではなく、最初のレンダリングエラーなしで動作しますか?私はリファクタリングが効果的に同じロジックフローを維持していると思ったが、何かが欠けているはずですか?あなたのリファクタリングバージョン

github.loadIssues().data

答えて

1

は常にその約束のデータプロパティは常に未定義となりますので、未定義になるだろう。

元のバージョンでは、this.issuesはAPIから返されたデータが一度しか設定されていないため、これまで設定されていた唯一の値は初期値[]とAPI応答の塗りつぶしの配列でした。

あなたの場合、3つの状態は[] - > undefined - >と塗りつぶしの配列です。

@computed get buildIssues() { 
    github.loadIssues().then((data) => { 
     this.issues = data 
    }).catch((err) => { 
     // handle err. 
    }) 
} 
+0

ありがとう:

buildIssuesは、次のようになります!働いた。私の約束を理解するだけでは、私のデータを入手するという約束が返って来たときになぜ別の '.then()'が必要なのか理解できませんでした。私は、約束の中で定義されている '.then()'は、応答の中で必要なものを取り出すのに十分であると仮定しました。 – changingrainbows

関連する問題