简体   繁体   English

在 React 中将状态数组从一个组件传递到另一个组件

[英]Passing state array from one component to another in React

I have a saved[] array in my component.我的组件中有一个saved[]数组。 I want to pass this data from one component to another.我想将此数据从一个组件传递到另一个组件。

I have tried the following:我尝试了以下方法:

<Home default path='/news' savedArticles={this.state.saved}/>

But this throws an error as it says TypeError: Cannot read property 'saved' of null但这会引发错误,因为它说TypeError: Cannot read property 'saved' of null

So this is the component which has they data.所以这是拥有他们数据的组件。

NewsMain.js新闻Main.js

import React, { Component } from 'react';
import '../news-main/news-main.css';
import News from '../news/news';
import NewsHero from '../news-hero/news-hero';
import Sports from '../sports/sports';

class NewsMain extends Component {
    render() {
        return (
            <div>
                <NewsHero />
                <News />
                <Sports />
            </div>
        )
    }
}
export default NewsMain;

The data comes from the NewsHero /> component.数据来自NewsHero />组件。

news.hero.js新闻.hero.js

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 = headline => {
        this.setState(
         (prevState) => ({ saved: [...prevState.saved, headline] }),
          () => {
            console.log('Saved articles = ', this.state.saved);
            alert('Article saved');
            localStorage.setItem('saved', JSON.stringify(this.state.saved));
            localStorage.getItem('saved');
          });
      }

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

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

    componentDidMount() {
        this.setState({ loading: true, saved: localStorage.getItem('saved') ? JSON.parse(localStorage.getItem('saved')) : [] })
        fetch('https://newsapi.org/v2/everything?q=timbaland&domains=rollingstone.com,billboard.com&excludeDomains=townsquare.media&apiKey=8ee8c21b20d24b37856fc3ab1e22a1e5')
            .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(post)}>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;

I want to pass the saved array to other components eg我想将保存的数组传递给其他组件,例如

app.js应用程序.js

import React, { Component } from 'react';
// import logo from './logo.svg';
import './App.css';
import Header from './header/header';
import NewsMain from './news-main/news-main';
import Footer from './footer/footer';
import Home from './home/home';
import { Router } from '@reach/router';

class App extends Component {

  render() {
    return (
      <div className="App">
        <Header />
        <div>
          <Router>
            <Home default path='/news' savedArticles={this.state.saved} />
            <NewsMain path='/news' />
          </Router>
        </div>
        <Footer title="Footer" />
      </div>
    )
  }
}
export default App;

Any idea's?有任何想法吗?

In your code, you are passing property "saved" from object "state" to Home before you are declaring any state.在您的代码中,在声明任何状态之前,您将属性“保存”从对象“状态”传递到 Home。

this.state in render method of your App componend is state only of your App component.您的 App 组件的 render 方法中的 this.state 仅是您的 App 组件的状态。 I believe that you would like to use property from state of NewsHero component.我相信您想使用 NewsHero 组件状态中的属性。 This property is only accessible within NewsHero component and you have to somehow pass it up to App component and only then you can pass it down toward Home.这个属性只能在 NewsHero 组件中访问,你必须以某种方式将它传递给 App 组件,然后你才能将它传递给 Home。

You can also use some global state or some other state library like Redux, but clearly you have to refractor given code您还可以使用一些全局状态或其他一些状态库,如 Redux,但显然您必须折射给定的代码

You have not initiated your state anywhere in your app, so this.state is undefined .你还没有在你的应用程序的任何地方启动你的状态,所以this.stateundefined

Your app.js should look like this:你的 app.js 应该是这样的:

import React, { Component } from 'react';
// import logo from './logo.svg';
import './App.css';
import Header from './header/header';
import NewsMain from './news-main/news-main';
import Footer from './footer/footer';
import Home from './home/home';
import { Router } from '@reach/router';

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {saved: []};
  }
  render() {
    return (
      <div className="App">
        <Header />
        <div>
          <Router>
            <Home default path='/news' savedArticles={this.state.saved} />
            <NewsMain path='/news' />
          </Router>
        </div>
        <Footer title="Footer" />
      </div>
    )
  }
}
export default App;

Take a look here https://it.reactjs.org/docs/state-and-lifecycle.html for more info on state and lifecycle in reactjs.在此处查看https://it.reactjs.org/docs/state-and-lifecycle.html ,了解有关 reactjs 中状态和生命周期的更多信息。

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

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