简体   繁体   English

将对象从 JSON rest api 推送到在 React 中不起作用的空数组

[英]Push object from JSON rest api into empty array not working in React

I am trying to push a object from a JSON response from a rest api into an empty array in React, so far my code is not working, I am fairly new to React so can't see where I am going wrong?我正在尝试将来自rest api的JSON响应中的对象推送到React中的空数组中,到目前为止我的代码无法正常工作,我对React还很陌生,所以看不出我哪里出错了? Maybe something to do with the function in the state?也许与状态中的功能有关? I am getting error:我收到错误:

Cannot read property 'saved' of undefined

code so far:到目前为止的代码:

import React, { Component } from 'react';
import './news-hero.css';
import Carousel from "react-multi-carousel";
import "react-multi-carousel/lib/styles.css";

const responsive = {
    superLargeDesktop: {
        breakpoint: { max: 4000, min: 3000 },
        items: 1,
    },
    desktop: {
        breakpoint: { max: 3000, min: 1024 },
        items: 1,
    },
    tablet: {
        breakpoint: { max: 1024, min: 464 },
        items: 1,
    },
    mobile: {
        breakpoint: { max: 464, min: 0 },
        items: 1,
    },
};

class NewsHero extends Component {
    state = {
        loading: false,
        data: [],
        headline: [],
        saved: []
    }

    saved() {
        this.saved.push(this.headline);
        //alert('this is saved kind of');
    }

    onError() {
        this.setState({
            imageUrl: "../assets/img-error.jpg"
        })
    }

    componentDidMount() {
        this.setState({ loading: true })
        fetch('https://newsapi.org/v2/everything?q=timbaland&domains=rollingstone.com,billboard.com&excludeDomains=townsquare.media&apiKey=8')
            .then(headline => headline.json())
            .then(headline => this.setState({ headline: headline.articles, loading: false }, () => console.log(headline.articles)))
    }

    render() {
        return (
            <div className="hero">
                <h2 className="text-left">News</h2>

                {this.state.loading
                    ? "loading..."
                    : <div>
                        <Carousel
                            additionalTransfrom={0}
                            showDots={true}
                            arrows={true}
                            autoPlaySpeed={3000}
                            autoPlay={false}
                            centerMode={false}
                            className="carousel-hero"
                            containerClass="container-with-dots"
                            dotListClass="dots"
                            draggable
                            focusOnSelect={false}
                            infinite
                            itemClass="carousel-top"
                            keyBoardControl
                            minimumTouchDrag={80}
                            renderButtonGroupOutside={false}
                            renderDotsOutside
                            responsive={responsive}>
                            {this.state.headline.map((post, indx) => {
                                return (
                                    <div className="text-left mt-5" key={indx}>
                                        <img className="media-img card-img-top card-img-hero" src={post.urlToImage} alt="Alt text"></img>
                                            <div className="card-body container hero-text-body">
                                                <h1 className="card-title hero-title text-truncate">{post.title}</h1>
                                                <button className="btn-primary btn mt-2 mb-4" onClick={this.saved}>Add this article</button>
                                                <p className="card-text">{post.description}</p>
                                                <a href={post.url} target="_blank" rel="noopener noreferrer">Read More</a>
                                            </div>
                                    </div>
                                )
                            })}
                        </Carousel>

                    </div>
                }
            </div>
        )
    }
}
export default NewsHero;

Any idea's and insight?任何想法和见解?

Cannot read property 'saved' of undefined无法读取未定义的属性“已保存”

You are not correctly referencing this.state for saved or headline .您没有正确引用this.statesavedheadline

Cannot read property 'state' of undefined无法读取未定义的属性“状态”

Either add a constructor and bind this to your saved function.无论是构造并绑定添加this对您的saved功能。

constructor(props) {
  super(props);
  this.saved = this.saved.bind(this);
}

saved() {
    this.saved.push(this.headline);
    //alert('this is saved kind of');
}

Or define saved as an arrow function to bind this或者定义saved为箭头函数来绑定this

saved = () => {
    this.saved.push(this.headline);
    //alert('this is saved kind of');
}

Should be应该

saved() {
  const { headline, saved } = this.state;
  this.setState({ saved: [...saved, headline] });
}

or或者

saved = () => {
  const { headline, saved } = this.state;
  this.setState({ saved: [...saved, headline] });
}

UPDATE: Save a specific post/headline更新:保存特定的帖子/标题

I see now, if you wish to save a specific headline then you need to update the signature of your saved function and how you call it.我现在看,如果你想保存特定的标题,那么你需要更新你的签名saved功能你怎么称呼它。

saved = headline => {
  this.setState(
    prevState => ({ saved: [...prevState.saved, headline] })
  );
}

and when you invoke it as a callback当您将其作为回调调用时

<button
  className="btn-primary btn mt-2 mb-4"
  onClick={() => this.saved(post)} // pass the current post defined in the map callback
>
  Add this article
</button>

One minor comment about naming, consistently referencing the same "object" the same way throughout code goes a long way in helping readability.关于命名,始终引用相同的“对象”,整个代码相同的方法之一轻微评论帮助可读性很长的路要走 IE how you reference headlines, posts, and articles. IE 如何引用标题、帖子和文章。 Pick one and be consistent.选择一个并保持一致。

this.state.headlines => this.state.headlines.map(headline => ... this.state.headlines => this.state.headlines.map(headline => ...

this.state.posts => this.state.posts.map(post => ... this.state.posts => this.state.posts.map(post => ...

this.state.articles => this.state.articles.map(article => ... this.state.articles => this.state.articles.map(article => ...

    saved() {
        this.saved.push(this.headline);
        //alert('this is saved kind of');
    }

You cannot defined class methods like this without writing a constructor like this:如果不编写这样的构造函数,就不能定义这样的类方法:

class NewsHero extends Component {
  constructor(props){
    super(props)
    this.saved = this.saved.bind(this)

  }

...the rest of everything you wrote

}

Without doing this, your saved function is not bound to the instance of the class.如果不这样做,您saved函数就不会绑定到类的实例。 Its silly, yes, but that's how class methods work in javasript.是的,这很愚蠢,但这就是 javasript 中类方法的工作方式。 The other option is to use an arrow function, which preserves the context if this :另一种选择是使用箭头函数,如果出现this情况,它会保留上下文:

    saved = () => {
        this.saved.push(this.headline);
        //alert('this is saved kind of');
    }

I think this is faster and cleaner, and its pretty commonly used.我认为这更快更干净,而且非常常用。

That is problem 1. Problem 2 is that it appears you are trying to modify the state object directly when writing this.saved.push(this.headline) .那是问题 1。问题 2 是您在编写this.saved.push(this.headline)时似乎试图直接修改状态对象。 That's not how to do it.这不是怎么做的。 To modify your state, you need to use the this.setState function:要修改您的状态,您需要使用this.setState函数:

saved = () => {
  this.setState({
    saved: whatever you want this to be
  })
}

But it looks like you are already setting your state correctly in your fetch call, so I'm not sure what you're trying to accomplish with your saved function...?但是看起来您已经在 fetch 调用中正确设置了状态,所以我不确定您要使用saved函数完成什么...?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM