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

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

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

Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

JavaScript

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

React.js

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

Q&A

解決済

1回答

4335閲覧

Reactで'setState' of nullのエラーが解決できない

psp7

総合スコア11

Firebase

Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

JavaScript

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

React.js

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

1グッド

1クリップ

投稿2017/11/26 05:32

編集2017/11/26 06:26

初めて質問させていただきます。

最近,React.jsを勉強し始めたのですが、setStateメソッドの部分で'setState' of nullというエラーが出てしまい、全く先に進めなくなってしまいました。
Reactについて詳しい方にご教授いただければと思います。

開発環境: React.js + Firebase

databaseには、firebaseを使っており、ここからデータを読み込んで、Stateのtweetsに値を格納したいと思っております。格納できれば解決するのですが、どうしてもわかりません。
コードは以下です。

このコードで、componentDidMount()のthis.setStateの部分でエラーが起きてしまいます。

エラー文は以下です。

error

1Uncaught TypeError: Cannot read property 'setState' of null

React.js

1<!DOCTYPE html> 2<html> 3<head> 4 <meta charset="UTF-8"> 5 <meta lang="ja"> 6 <link rel="stylesheet" type="text/css" href="css/style.css"> 7 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.js"></script> 8 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.js"></script> 9 <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.34/browser.min.js"></script> 10 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script> 11 <script src="https://www.gstatic.com/firebasejs/4.6.2/firebase.js"></script> 12</head> 13 14<body> 15 <div id="tweet"></div> 16 17 <script type="text/babel"> 18 // Initialize Firebase 19 var config = { 20 ********非表示にしています****** 21 }; 22 firebase.initializeApp(config); 23 24 var firebaseRef = firebase.database().ref(); 25 var tweetsRef = firebaseRef.child("tweets"); 26 27 // メインツイート画面 28 class TweetContainer extends React.Component{ 29 30 constructor(props) { 31 super(props); 32 this.state = {tweets: [ 33 { id: 1, user: 'Tom', text: 'Good morning' }, 34 { id: 2, user: 'John', text: 'Good afternoon' }, 35 { id: 3, user: 'Emily', text: 'Good evening' } 36 ]}; 37 console.log("initialized"); 38 39 this.componentDidMount = this.componentDidMount.bind(this); 40 } 41 42 componentDidMount(){ 43 tweetsRef.on("value", function(snapshot){ 44 this.setState({ //エラー部分 45 tweets: snapshot.val() 46 }); 47 }); 48 } 49 50 render(){ 51 var tweetItems = this.state.tweets.map(function(tweet){ 52 return ( 53 <TweetItem tweet={tweet} /> 54 ); 55 }); 56 57 return( 58 <div className="tweetContainer"> 59 {tweetItems} 60 <TweetForm /> 61 </div> 62 ); 63 } 64 } 65 66 //ツイートアイテム 67 class TweetItem extends React.Component{ 68 constructor(props) { 69 super(props); 70 } 71 72 render(){ 73 return( 74 <div className="tweetItem"> 75 <div className="tweet">{this.props.tweet.text}</div> 76 </div> 77 ); 78 } 79 } 80 81 //送信フォーム 82 class TweetForm extends React.Component{ 83 constructor(props) { 84 super(props); 85 this._onClick = this._onClick.bind(this); 86 } 87 88 _onClick(e){ 89 tweetsRef.push({ 90 text: ReactDOM.findDOMNode(this.refs.inputValue).value 91 }); 92 } 93 94 render(){ 95 return( 96 <div className="tweetForm"> 97 <input ref="inputValue" type="text" placeholder="message..." /> 98 <input type="button" value="送信" onClick={this._onClick.bind(this)}/> 99 </div> 100 ); 101 } 102 } 103 104 //レンダリング 105 ReactDOM.render( 106 <TweetContainer />, 107 document.getElementById("tweet") 108 ); 109 </script> 110 111</body> 112</html> 113
gesorein👍を押しています

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

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

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

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

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

guest

回答1

0

ベストアンサー

Javascript/Reactに詳しくないので、命知らずなコメントですが...

最近ちょうど似たような議論を見ました

teratail: Reactにおける関数の渡し方による動作の違い

上記のraccyさんの回答にあるthisの議論が参考になるように思います。

javascript

1componentDidMount(){ 2 tweetsRef.on("value", function(snapshot){ 3 this.setState({ 4 tweets: snapshot.val() 5 }); 6 }); 7}

functionの本体部分でthisを参照する際、この関数が

f.call(eventSource, snapShot)

と呼び出されるのであれば関数内のthisはeventSourceに束縛されますが、この場合はeventSourceがイベント発生元のインスタンス(tweetsRefの値)になるなら、thisは質問者さんが意図したものにならないのではないでしょうか。質問者さんの意図はthisがTweetContainerのインスタンスを表すことですよね?

対処:

class構文をお使いなので(ES2015前提なので)、functionによる無名関数ではなくアロー関数を使えば次のように書けると思います。

javascript

1componentDidMount() { 2 tweetsRef.on("value", snapshot => this.setState({ 3 tweets: snapshot.val() 4 }); 5}

functionキーワードによる無名関数とアロー関数のthisの違いは次のような単純な例を見ると観察できます。無名関数はcallで起動される際の第一引数の値がthisに束縛されてから実行されますが、アロー関数はアロー関数が生成された時点の文脈でのthisが束縛されたクロージャーの元で実行されるので、callで起動されたとしてもその第一引数の値によりthisが変化することはないのだと思います。

javascript

1function A() { 2 this.a = 1; 3 4 // 無名関数f本体のthisは関数生成時点のクロージャー内に束縛されて 5 // おらず、f.call(x)で起動された際のxの値で(起動時に)束縛される。 6 A.prototype.f = function () { return this.a; }; 7} 8 9function B() { 10 this.a = 1; 11 12 // アロー関数本体のthisはアロー関数生成時点のクロージャー内に束縛される。 13 B.prototype.f = () => this.a; 14} 15 16let a = new A(); 17let b = new B(); 18console.log(a.f.call({a: 2}); // 2 19console.log(b.f.call({a: 2}); // 1

おかしな点がありましたら指摘いただけると幸いです。

投稿2017/11/26 12:47

KSwordOfHaste

総合スコア18394

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

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

psp7

2017/11/26 12:56

KSwordOfHasteさん、ありがとうございます! 実は先ほど解決したのですが、まさにおっしゃる通り、thisが親のコンポーネントを指定できていないことが原因でした。ご説明いただいたアロー関数を使うことにより、問題のエラーは起きなくなりました。 componentDidMount(){ tweetsRef.on("value", (snapshot) => { this.setState({ tweets: snapshot.val() }); }); } かなりマイナーな質問にも関わらず、的確な回答をいただきありがとうございました。 自分もまだまだReact.jsを始めたばかりなので、もっと勉強します。
KSwordOfHaste

2017/11/26 13:03

自分もちょうど先日「なんでthisが思った通りにならないのだろう」としばらく悩んでいたのです。JSの落とし穴なのかも知れません。思い出してみると本サイトでも過去にそういう話が出てきてたと思いますが自分自身が充分その意味を掴めてなかったのだと思います。bindの意味とかようやく実感できました。
psp7

2017/11/26 18:47

ES6かなんか、バージョンが変わって書き方が変わってたみたいですね。 それまではthisをバインドしなくても勝手に認識してくれてたみたいなんですけど、それが自動じゃ無くなってたみたいです。 React.jsは調べても古い書き方が多くて惑わされるので大変ですね...w
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問