web-dev-qa-db-ja.com

Reactコンポーネントを返すと、配列にアクセスしようとした後、nullのプロパティ '__reactInternalInstance $を読み取ることができません

ここに問題のある問題のあるコンポーネントがあります。

const UserList = React.createClass({
  render: function(){
    let theList;
    if(this.props.data){
      theList=this.props.data.map(function(user, pos){
        return (
          <div className="row user">
            <div className="col-xs-1">{pos}</div>
            <div className="col-xs-5">{user.username}</div>
            <div className="col-xs-3">{user.recent}</div>
            <div className="col-xs-3">{user.alltime}</div>
          </div>
        );
      }, this);
    } else {
     theList = <div>I don't know anymore</div>;
    }
    console.log(theList);
    return (
      theList
    );
  }
});

{theList}を返そうとすると、Cannot read property '__reactInternalInstance $ mincana79xce0t6kk1s5g66r' of nullエラーが表示されます。ただし、{theList}を静的なhtmlで置き換えると、console.logは必要なオブジェクトの正しい配列を出力します。回答に従って、{theList}とtheListの両方を返そうとしましたが、それは役に立ちませんでした。

どちらの場合も、console.logは最初に[]を出力します。これは、componentDidMountにサーバーからjsonを取得するためのajax呼び出しが含まれており、最初のrender()の前にまだ起動していないためです。 this.props.dataがnullであることを確認しようとしましたが、役に立ちません。

これが役立つ場合の親コンポーネントは次のとおりです。

const Leaderboard = React.createClass({
  getInitialState: function(){
    return ({data: [], mode: 0});
  },
  componentDidMount: function(){
    $.ajax({
      url: 'https://someurlthatreturnsjson',
      dataType: 'json',
      cache: false,
      success: function(data) {
        this.setState({data: data});
      }.bind(this),
      error: function(xhr, status, err) {
        console.error('https://someurlthatreturnsjson', status, err.toString());
      }.bind(this)
    });
  },
  render: function(){
    return (
      <div className="leaderboard">
        <div className="row titleBar">
          <img src="http://someimage.jpg"></img>Leaderboard
        </div> 
        <HeaderBar />
        <UserList data={this.state.data}/>
      </div>
    );
  }
}); 
10

ええと、ここにはいくつかの興味深い問題がありましたが、あなたはso closeでした。大きな要素は、reactを使用する場合、常に単一の最上位要素(divなど)を返す必要があります。したがって、変数theListは実際にはdivの配列でした。直接返品することはできません。ただし、単一の親divにラップされている場合は、それを返すことができます。

const mockData = [
        {
        username: 'bob',
    recent: 'seven',
    alltime: 123,
  },
        {
        username: 'sally mae',
    recent: 'seven',
    alltime: 133999,
  },
];

var $ = {
        ajax(opt) {
        setTimeout(() => {
        opt.success(mockData);
    }, 200);
  }
}

const UserList = React.createClass({
  render: function(){
        let theList;
    if (this.props.data && this.props.data.length) {
      theList = this.props.data.map(function(user, pos){
        return (
          <div key={user.username} className="row user">
            <div className="col">{pos}</div>
            <div className="col">{user.username}</div>
            <div className="col">{user.recent}</div>
            <div className="col">{user.alltime}</div>
          </div>
        );
      });
    } else {
      theList = <div>There is NO data</div>;
    }
    
    return <div>{theList}</div>;
  }
});

const Leaderboard = React.createClass({
  getInitialState: function(){
    return ({data: [], mode: 0});
  },
  componentDidMount: function(){
    $.ajax({
      url: 'https://someurlthatreturnsjson',
      dataType: 'json',
      cache: false,
      success: function(data) {
        this.setState({data: data});
      }.bind(this),
      error: function(xhr, status, err) {
        console.error('https://someurlthatreturnsjson', status, err.toString());
      }.bind(this)
    });
  },
  render: function(){
    return (
      <div className="leaderboard">
        <UserList data={this.state.data}/>
      </div>
    );
  }
}); 

ReactDOM.render(
  <Leaderboard/>,
  document.getElementById('container')
);
.col {
  width: 200px;
  float: left;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://facebook.github.io/react/js/jsfiddle-integration-babel.js"></script>

<div id="container">
  <!-- This element's contents will be replaced with your component. -->
</div>

フィドルを少し説明します。奇妙に見えることを心配しないでくださいvar $もの、私はjQueryのajaxメソッドをスタブアウトしているだけなので、200ms後に偽のデータを返すことができます。

また、私にとってjsfiddleを実行すると「bad config」メッセージが表示されますが、メッセージを閉じると結果が表示されます。それが何であるか分からない。

8
return (
  {theList}
)

ちょうどである必要があります

return theList

その時点ではJSX内にいないためです。あなたがそこで行っていることは次のように解釈されます

return {
  theList: theList
}

これがES6の省略プロパティ構文です。

4
Jeff

エラーは、存在しないネストされた状態へのアクセスからも発生する可能性があります。

私にはコメントする評判がないので、将来の支援のための回答を追加します-別の理由でこの同じ問題に遭遇しました。どうやら、エラーはreactの内部状態をスローする以前のエラーからトリガーされましたが、エラーはどういうわけかキャッチされています。 github issue#8091

私の場合、プロパティをreduxストアに移動した後、存在しない状態のプロパティにアクセスしようとしました。

// original state
state: {
  files: [],
  user: {},
}
// ... within render function:
<h1> Welcome {this.state.user.username} </h1>

続いてユーザーをreduxストアに移動し、状態から行を削除しました//変更された状態state:{files:[]、} // ... render関数内(変更を忘れた):

<h1> Welcome {this.state.user.username} </h1>

そして、これは不可解なエラーを投げました。 this.props.user.usernameを呼び出すようにrenderを変更することで、すべてがクリアされました。

1
Reid Henderson

ステートレスコンポーネントをレンダリングし、基本的なdom操作でレンダリングした後、react-root-element(ラッピングdiv)を削除することにしたときに、このエラーが発生しました。

結論:これに注意してください。実行しないことをお勧めします。

0
ant45de

Ifステートメントには小さな問題があります。

if(this.props.data !== []){

でなければなりません:

if(this.props.data){

this.props.dataは、ajax呼び出しがnullを返す場合はnullです。あるいは、コードをより複雑にすることもできます。

const data = this.props.data;
if(data && data.constructor === Array && data.length > 0) {
0
vijayst

これがあなたのやりたいことかどうかはわかりませんが、私にとってはうまくいきます。

編集:

const UserList = React.createClass({
  render: function() {
    if(this.props.data){
      return this.props.data.map(function(user, pos){
        return (
          <li> className="row user">
            <span>{pos}</span>
            <span>{user.username}</span>
            <span>{user.recent}</span>
            <span>{user.alltime}</span>
          </li>
        );
      });
    } else {
      return <li>I don't know anymore</li>;
    }
  }
});
0
alexi2