ReactJS:在onClick调用后,对象的属性变为未定义

时间:2018-03-29 14:31:13

标签: reactjs

我制作了一个简单的React应用程序来显示一些带引号的图像卡。它工作得很好,但后来我重构了我的代码,因为我收到一个警告,使用setState而不是直接改变状态属性。然后我开始收到此错误:

App.js:111 Uncaught TypeError: Cannot read property 'imageURL' of undefined

我想这意味着即使以前工作过,我也没有做好。我怀疑我的问题与setState异步有关,但我找不到解决方案。任何关于此事的光线都会非常感激!

以下代码:

更新:

感谢您的建议!我这里有一些更新的代码,它仍然返回相同的错误。以下是所要求的最新文件:

App.js: https://pastebin.com/daBTNKc7
App.css: https://pastebin.com/68xZdLfT
quotesData.json https://pastebin.com/1xD5DS0z

更新2:

我意识到我并没有以合理的方式初始化this.state.cards,所以当render()试图读取它时,数​​组是空的。我更改了构造函数以使用一些占位符数据初始化数组,如下所示:

constructor(props) {
    super(props);

    this.state = {
        imagesLoaded: false,
        cards: [],
        numItems: 6,
        numLoaded: 0,
        quotes: quoteData
    };


    for (var i = 0; i < this.state.numItems; i++) {

        var quoteObject = ["Inspiring quote goes here.", "Speaker Name"];

        var cardObject = {
            imageURL: './src/placeholder.png',
            quote: quoteObject[0],
            credit: quoteObject[1]
        };

        this.state.cards.push(cardObject);

        //Sleep between requests so Unsplash doesn't block us for overloading it.
        this.sleep(500);
    }

    this.getRandomQuote = this.getRandomQuote.bind(this);
    this.renderCard = this.renderCard.bind(this);
}

它现在正在工作 - 感谢大家的帮助!它仍然需要改进,但希望我可以自己完成其余部分。

2 个答案:

答案 0 :(得分:0)

如果不是真的有必要(不会导致多次渲染),则不应多次使用同一方法调用setState。此外,setState是一种异步方法。

e.g。你应该在方法refreshImages结束时这样做:

this.setState({
  imagesLoaded: false,
  numLoaded: 0,
  cards: result
});

对于其他方法也一样。

有关setState的更多信息,请参阅文档: https://reactjs.org/docs/react-component.html#setstate

希望这有帮助。

答案 1 :(得分:0)

您有几个错误。以下不是全部,但这是一个好的开始:) 修复这些内容,发布更新后的代码,同时发布quotesData.jsonApp.css,我们会继续......

首先修复以下内容:

您不能从构造函数中设置set。

在构造函数之后添加以下内容(并从构造函数中删除对refreshImages的调用)。

componentDidMount() {  
  this.refreshImages();  
}

&#39;这&#39;未在以下情况下正确设置:

getRandomQuote();  
renderCard();

在构造函数中添加以下内容:

this.getRandomQuote = this.getRandomQuote.bind(this);
this.renderCard = this.renderCard.bind(this);

更新后,您几乎就在那里:)

剩下的问题是,尽管您将卡值设置在正确的位置(componentDidMount),但setState是异步的,因此第一次输入render()时,卡仍未设置。

我替换了以下行:

if (this.state.imagesLoaded) {

以下内容:

if (this.state.cards.length === 0) {
  return (
    <div className="App">
      <header className="App-header">
        <h1 className="App-title">state.images still empty</h1>
      </header>
    </div>
  );  
} else if (this.state.imagesLoaded) {

我看到带有漂亮图像的智能引号:)

这是一种解决方法,当然,你需要决定做什么...... 还有,真的需要在refreshImages中睡眠(500)吗?

还有一条建议(与您遇到的问题无关):使用reactstrap,它会让您的生活更轻松。你需要知道bootstrap,这很容易学习(但不要使用bootstrap,使用reactstrap)。

祝你工作顺利:))