रिएक्ट जेएस - अनकैप्ड टाइपर्रर: this.props.data.map एक फ़ंक्शन नहीं है


111

जब मैं JSON डेटा (या तो फ़ाइल या सर्वर से) प्रदर्शित करने की कोशिश कर रहा हूँ, तो मैं प्रतिक्रिया के साथ काम कर रहा हूँ और इस त्रुटि को रोक नहीं सकता।

Uncaught TypeError: this.props.data.map is not a function

मैंने देखा है:

रिएक्ट कोड "टाइप टाइप: थ्रू: इस.प्रॉप्सडेटा.मैप एक फंक्शन नहीं है"

React.js इस। Props.data.map () एक फ़ंक्शन नहीं है

इनमें से किसी ने भी समस्या को ठीक करने में मेरी मदद नहीं की। मेरे पेज लोड होने के बाद, मैं सत्यापित कर सकता हूं कि यह.data.props अपरिभाषित नहीं है (और इसमें JSON ऑब्जेक्ट के बराबर मूल्य है - के साथ कॉल कर सकते हैं window.foo), इसलिए ऐसा लगता है कि यह समय में लोड नहीं हो रहा है जब इसे कहा जाता है ConversationList। मैं यह कैसे सुनिश्चित करूं कि mapविधि JSON डेटा पर काम कर रही है न कि एक undefinedचर पर?

var converter = new Showdown.converter();

var Conversation = React.createClass({
  render: function() {
    var rawMarkup = converter.makeHtml(this.props.children.toString());
    return (
      <div className="conversation panel panel-default">
        <div className="panel-heading">
          <h3 className="panel-title">
            {this.props.id}
            {this.props.last_message_snippet}
            {this.props.other_user_id}
          </h3>
        </div>
        <div className="panel-body">
          <span dangerouslySetInnerHTML={{__html: rawMarkup}} />
        </div>
      </div>
    );
  }
});

var ConversationList = React.createClass({
  render: function() {

    window.foo            = this.props.data;
    var conversationNodes = this.props.data.map(function(conversation, index) {

      return (
        <Conversation id={conversation.id} key={index}>
          last_message_snippet={conversation.last_message_snippet}
          other_user_id={conversation.other_user_id}
        </Conversation>
      );
    });

    return (
      <div className="conversationList">
        {conversationNodes}
      </div>
    );
  }
});

var ConversationBox = React.createClass({
  loadConversationsFromServer: function() {
    return $.ajax({
      url: this.props.url,
      dataType: 'json',
      success: function(data) {
        this.setState({data: data});
      }.bind(this),
      error: function(xhr, status, err) {
        console.error(this.props.url, status, err.toString());
      }.bind(this)
    });
  },
  getInitialState: function() {
    return {data: []};
  },
  componentDidMount: function() {
    this.loadConversationsFromServer();
    setInterval(this.loadConversationsFromServer, this.props.pollInterval);
  },
  render: function() {
    return (
      <div className="conversationBox">
        <h1>Conversations</h1>
        <ConversationList data={this.state.data} />
      </div>
    );
  }
});

$(document).on("page:change", function() {
  var $content = $("#content");
  if ($content.length > 0) {
    React.render(
      <ConversationBox url="/conversations.json" pollInterval={20000} />,
      document.getElementById('content')
    );
  }
})

संपादित करें: नमूना वार्तालाप जोड़ रहे हैं

नोट - कॉलिंग में this.props.data.conversationsभी त्रुटि होती है:

var conversationNodes = this.props.data.conversations.map...

निम्न त्रुटि देता है:

अनक्रेड टाइप टाइप: अपरिभाषित की संपत्ति 'नक्शा' नहीं पढ़ सकता है

यहाँ वार्तालाप है। संदेश:

{"user_has_unread_messages":false,"unread_messages_count":0,"conversations":[{"id":18768,"last_message_snippet":"Lorem ipsum","other_user_id":10193}]}

मैंने जवाब अपडेट कर दिया है। इसके अलावा, कुछ सिफारिशें: PropTypes: {data: React.PropTypes.array} को कन्वर्सेशन में जोड़ें ताकि डेटा के प्रकार को सत्यापित किया जा सके और एक घटकWillUnmount जोड़ें: fn () जो "ClearInterval": कन्वर्सेशनबॉक्स में अंतराल।
user120242

जवाबों:


135

.mapसमारोह सरणी पर ही उपलब्ध है।
ऐसा लगता dataहै कि आप उस प्रारूप में नहीं हैं जिससे आप यह होने की उम्मीद कर रहे हैं (यह {} है, लेकिन आप []] की उम्मीद कर रहे हैं।

this.setState({data: data});

होना चाहिए

this.setState({data: data.conversations});

जांचें कि किस प्रकार का "डेटा" सेट किया जा रहा है, और सुनिश्चित करें कि यह एक सरणी है।

कुछ सिफारिशों के साथ संशोधित कोड (प्रचार सत्यापन और स्पष्टता):

var converter = new Showdown.converter();

var Conversation = React.createClass({
  render: function() {
    var rawMarkup = converter.makeHtml(this.props.children.toString());
    return (
      <div className="conversation panel panel-default">
        <div className="panel-heading">
          <h3 className="panel-title">
            {this.props.id}
            {this.props.last_message_snippet}
            {this.props.other_user_id}
          </h3>
        </div>
        <div className="panel-body">
          <span dangerouslySetInnerHTML={{__html: rawMarkup}} />
        </div>
      </div>
    );
  }
});

var ConversationList = React.createClass({
 // Make sure this.props.data is an array
  propTypes: {
    data: React.PropTypes.array.isRequired
  },
  render: function() {

    window.foo            = this.props.data;
    var conversationNodes = this.props.data.map(function(conversation, index) {

      return (
        <Conversation id={conversation.id} key={index}>
          last_message_snippet={conversation.last_message_snippet}
          other_user_id={conversation.other_user_id}
        </Conversation>
      );
    });

    return (
      <div className="conversationList">
        {conversationNodes}
      </div>
    );
  }
});

var ConversationBox = React.createClass({
  loadConversationsFromServer: function() {
    return $.ajax({
      url: this.props.url,
      dataType: 'json',
      success: function(data) {
        this.setState({data: data.conversations});
      }.bind(this),
      error: function(xhr, status, err) {
        console.error(this.props.url, status, err.toString());
      }.bind(this)
    });
  },
  getInitialState: function() {
    return {data: []};
  },

 /* Taken from 
    https://facebook.github.io/react/docs/reusable-components.html#mixins
    clears all intervals after component is unmounted
  */
  componentWillMount: function() {
    this.intervals = [];
  },
  setInterval: function() {
    this.intervals.push(setInterval.apply(null, arguments));
  },
  componentWillUnmount: function() {
    this.intervals.map(clearInterval);
  },

  componentDidMount: function() {
    this.loadConversationsFromServer();
    this.setInterval(this.loadConversationsFromServer, this.props.pollInterval);
  },
  render: function() {
    return (
      <div className="conversationBox">
        <h1>Conversations</h1>
        <ConversationList data={this.state.data} />
      </div>
    );
  }
});

$(document).on("page:change", function() {
  var $content = $("#content");
  if ($content.length > 0) {
    React.render(
      <ConversationBox url="/conversations.json" pollInterval={20000} />,
      document.getElementById('content')
    );
  }
})

32

मेरे लिए जो काम किया है वह props.data को सरणी में परिवर्तित करके उपयोग कर data = Array.from(props.data); रहा है तब मैं data.map()फ़ंक्शन का उपयोग कर सकता हूं


1
मेरा प्रकार पहले से ही एक सरणी था जैसे टाइपऑफ सही चीज़ दिखा रहा था लंबाई भी सही थी लेकिन फिर भी, त्रुटि दिखाई दे रही थी। इसने मेरे लिए इसे ठीक कर दिया। धन्यवाद!
user1829319 2

10

अधिक आम तौर पर, आप नए डेटा को एक सरणी में परिवर्तित कर सकते हैं और कुछ का उपयोग कर सकते हैं:

var newData = this.state.data.concat([data]);  
this.setState({data: newData})

यह पैटर्न वास्तव में https://facebook.github.io/react/ पर Facebook के ToDo डेमो ऐप (अनुभाग "एक एप्लिकेशन" देखें) में उपयोग किया जाता है ।


1
यह एक साफ सुथरा टिप / चाल है, लेकिन मैं यह ध्यान रखना चाहता हूं कि यह वास्तविक समस्या का सामना करेगा और ओपी को हल नहीं करेगा। ओपी के मामले में यह मदद नहीं करेगा, क्योंकि डेटा अभी भी विकृत हो जाएगा (जो इरादा नहीं था)। बातचीत की संभावना सबसे अधिक खाली होगी क्योंकि सभी प्रॉप्स अशक्त होंगे। मैं इस टिप का उपयोग नहीं करने की सलाह दूंगा, जब तक कि आप सुनिश्चित नहीं हैं कि आपका डेटा आपके इच्छित प्रारूप में है, इसलिए आप अप्रत्याशित व्यवहार के साथ समाप्त नहीं होते हैं जब डेटा वापस नहीं होता है तो आपको लगता है कि यह होना चाहिए।
user120242

1

आपको इसे करने के लिए किसी सरणी की आवश्यकता नहीं है।

var ItemNode = this.state.data.map(function(itemData) {
return (
   <ComponentName title={itemData.title} key={itemData.id} number={itemData.id}/>
 );
});

कैसे अलग है भाई?
अमर पाठक

1

ऐसा इसलिए होता है क्योंकि घटक async डेटा आने से पहले प्रदान किया जाता है, आपको रेंडर करने से पहले नियंत्रण करना चाहिए।

मैंने इसे इस तरह हल किया:

render() {
    let partners = this.props && this.props.partners.length > 0 ?
        this.props.partners.map(p=>
            <li className = "partners" key={p.id}>
                <img src={p.img} alt={p.name}/> {p.name} </li>
        ) : <span></span>;

    return (
        <div>
            <ul>{partners}</ul>
        </div>
    );
}
  • संपत्ति के अशक्त / अपरिभाषित होने पर नक्शा हल नहीं हो सकता है, इसलिए मैंने पहले नियंत्रण किया

this.props && this.props.partners.length > 0 ?


0

mapफ़ंक्शन का उपयोग करने के लिए आपको ऑब्जेक्ट को एक सरणी में बदलने की आवश्यकता है :

const mad = Object.values(this.props.location.state);

जहां this.props.location.stateएक अन्य घटक में पारित वस्तु है।


हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.