I have a saved[] array in my component. 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
So this is the component which has they data.
NewsMain.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.
news.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 e.g.
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 {
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?