質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
ECMAScript

ECMAScriptとは、JavaScript類の標準を定めるために作られたスクリプト言語です。

JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

Q&A

解決済

2回答

796閲覧

[React] Hacker News API を使用して取得したJSON形式のデータを配列にparseできない

sabx

総合スコア200

ECMAScript

ECMAScriptとは、JavaScript類の標準を定めるために作られたスクリプト言語です。

JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

0グッド

0クリップ

投稿2018/05/30 12:13

わからないこと

掲題の通りですが、下記コードを実行するとエラーが発生してしまいます。
ただし、Chromeの開発コンソールから実行した場合は特にエラーは発生しません。

JavaScript

1import React from 'react'; 2import ReactDOM from 'react-dom'; 3 4 5class NewsList extends React.Component{ 6 render() { 7 /* Get all news ids */ 8 let xhttp = new XMLHttpRequest(); 9 xhttp.open("GET", "https://hacker-news.firebaseio.com/v0/topstories.json", true); 10 xhttp.setRequestHeader("Content-type", "application/json"); 11 xhttp.send(); 12 JSON.parse(xhttp.responseText); # ここで下に記載のエラーが発生 13 14 return( 15 <ol> 16 <li>Hello</li> 17 <li>World</li> 18 </ol> 19 ) 20 } 21} 22 23/* ================================== */ 24ReactDOM.render( 25 <NewsList />, 26 document.getElementById('root') 27);

エラー内容

SyntaxError: Unexpected end of JSON input

※Chromeの開発コンソールからrender()内を実行してもエラーにならず、parseはできました。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

エラーの理由は、XMLHttpRequstの処理は非同期であり、send()を読んだすぐあとではまだjsonが取得できていないということです。ですのでresponseTextはJSONでparse可能な文字列ではありません。Hayatoさんの仰るようにロードが完了してからparse処理をすると問題ないと思われます。

その上で2点アドバイスさせていただきます。

1点目は、Ajaxを行うのであれば、XMLHttpRequestは使わずにライブラリを使うことをオススメするということです。おすすめはaxiosです。クライアントjsで使えるいま一番アクティブなHTTPクライアントです。

2点目は、React Componentのrenderメソッドでデータの取得を行うべきではないという点です。renderは、propsやstateにあわせてreactiveに仮想DOMを構築するメソッドです。ですので、このメソッドの中で非同期のデータフェッチを行うことは避けるべきです。別のタイミング(例えばcomponentDidMount)でajaxでデータをフェッチし、setStateでVDOMを構築し直すのがthink in reactなやり方です。

私なら以下のように書くと思います。

js

1import React from 'react'; 2import ReactDOM from 'react-dom'; 3import axios from 'axios' 4 5class NewsList extends React.Component { 6 state = { 7 newsList: [] 8 } 9 async componentDidMount() { 10 try { 11 const {data} = await axios.get("https://hacker-news.firebaseio.com/v0/topstories.json"); 12 const newsList = JSON.parse(data); 13 this.setState({newsList}); 14 } catch(e) { 15 console.error(e); 16 } 17 } 18 render() { 19 return ( 20 <ul> 21 {this.state.newsList.map((v,i) => ( 22 <li key={`news-${i}`}>{v}</li> 23 ))} 24 <ul/> 25 ) 26 } 27} 28 29ReactDOM.render( 30 <NewsList />, 31 document.getElementById('root') 32);

ご参考までに。

投稿2018/05/30 15:42

keroxp

総合スコア114

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sabx

2018/06/02 05:33

ご連絡が遅くなりすいません。 XMLHttpRequestに関して、またReactやAjaxの際に使用するライブラリーなども教えていただきありがとうございました! 参考にさせていただきます…!
guest

0

ベストアンサー

let xhttp = new XMLHttpRequest(); xhttp.open("GET", "https://hacker-news.firebaseio.com/v0/topstories.json", true); xhttp.setRequestHeader("Content-type", "application/json"); xhttp.send(); xhttp.addEventListener('load', function (event) { console.log(JSON.parse(xhttp.responseText)); });

リクエストが完了して結果が帰ってきた後にJSON.parse()を実行してあげれば大丈夫かと思います。
https://codesandbox.io/s/yv3z86wl11

参考

追記

keroxpさんの回答にあるようにrenderメソッド内でAPIリクエストを行うのはよろしくありません。
パッとコードを見て回答をしてしまったので見落としていましたが、後から見る人用に回答に反映させておくべき点だと思いましたので、その部分を反映させたコードを追記させていただきます。

また、今回は質問の内容に寄せて、そのままXMLHttpRequestを使用しての回答をしましたが、実際の業務では、keroxpさんの回答にあるようにaxiosを使うか、もしくは(特に国外では)RxJSを使うのが一般的かと思います。

import React from 'react'; import ReactDOM from 'react-dom'; class NewsList extends React.Component { constructor(props) { super(props); this.state = { topStories: [] } this.xhr = new XMLHttpRequest(); } componentDidMount() { this.xhr.open("GET", "https://hacker-news.firebaseio.com/v0/topstories.json", true); this.xhr.setRequestHeader("Content-type", "application/json"); this.xhr.send(); this.xhr.addEventListener('load', this.handleOnLoad); this.xhr.addEventListener('error', this.handleOnError); this.xhr.addEventListener('abort', this.handleOnAbort); this.xhr.addEventListener('timeout', this.handleOnTimeout); this.xhr.addEventListener('progress', this.handleOnProgress); } handleOnLoad = (event) => { try { const responseData = JSON.parse(this.xhr.responseText); this.setState({ topStories: responseData }) } catch (error) { console.error(error); } } handleOnError = (event) => {} handleOnAbort = (event) => {} handleOnTimeout = (event) => {} handleOnProgress = (event) => {} componentWillUnmount() { this.xhr.abort(); this.xhr.removeEventListener('load', this.handleOnLoad); this.xhr.removeEventListener('error', this.handleOnError); this.xhr.removeEventListener('abort', this.handleOnAbort); this.xhr.removeEventListener('timeout', this.handleOnTimeout); this.xhr.removeEventListener('progress', this.handleOnProgress); } render() { return ( <ol> { this.state.topStories.map((storyId) => { return <li key={storyId}>{storyId}</li> }) } </ol> ) } } ReactDOM.render(<NewsList />, document.getElementById('root'));

投稿2018/05/30 14:00

編集2018/05/31 04:25
HayatoKamono

総合スコア2415

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sabx

2018/06/02 05:34

ご連絡が遅くなりすいません。 ご丁寧に追加で回答もしていただきありがとうございました! RxJSは使用したことがありませんので、今後トライしてみたいと思います! +αまで教えていただきまして本当にありがとうございました…!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問