Errors with passing data between components in ReactJS - javascript

I am trying to pass a state array from one component into another, to share and display the data. So the data is from a rest api that gets saved into an array called saved[]. I am trying to pass this into another component to display my saved articles. I have a few issues:
1 - No data is being displayed in the other component
2 - When switching between routes I get this error:
warning: Can't perform a React state update on an unmounted component.
So my code so far is as follows:
newshero.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=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(post)}>Add this article</button>
<p className="card-text">{post.description}</p>
Read More
</div>
</div>
)
})}
</Carousel>
</div>
}
</div>
)
}
}
export default NewsHero;
main-news.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;
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;
Trying to pass data into the below:
import React, { Component } from 'react';
import '../home/home.css';
class Home extends Component {
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=8')
.then(headline => headline.json())
.then(headline => this.setState({ headline: headline.articles, loading: false }, () => console.log('Saved articles', headline.articles)))
}
render() {
return (
<div className="mt-5 saved">
{this.props.savedArticles.map((article, indx) => {
return (
<div className="media mb-5" key={indx}>
<img className="media-img sports-thumb mr-3 mb-3 d-none d-sm-block" src={article.urlToImage} alt="Alt text"></img>
<div className="media-body text-left">
<h5 className="mt-0">{article.title}</h5>
<p className="text-left">{article.description}</p>
Read More
</div>
</div>
)
})}
</div>
)
}
}
export default Home;
Something to do with the state but I can't see where and why? Any idea's

Related

How to do mapping in reactjs if data is fetch in other file?

I have created a fileone.js file and I am trying to fetch the API data in this file as given below
import React, { Component, Suspense, lazy } from "react";
import axios from "axios";
import { ApiUrlConstant } from '../../../../utils/ApiUrlConstant';
import { getTokenu, isLoginu } from "../../../../utils/Token";
const Course = lazy(()=> import('../../../Course'));
const CourseDetails = lazy(()=> import('../../../CourseDetails'));
import Switch from "react-bootstrap/esm/Switch";
import PublicRoute from "../../../Route/Publicroute";
import FallBack from "../../FallBack/FallBack";
import "./Courses.scss";
class fileone extends Component {
constructor(props) {
super(props);
this.state = {
load: false,
checkPaid: true,
page: 0,
};
this.token = getTokenu();
}
setLoader = () => {
this.setState({ load: !this.state.load });
};
componentDidMount() {
axios.get(ApiUrlConstant.getApiFullUrl("course.feed"),
{
headers: {
Authorization: "Token " + this.token
}
})
.then((res) => {
this.setState({ User: res.data.results[0].user_detail.username, load: false });
this.setState({ Paid: res.data.results[0].user_paid, load: false });
this.setState({ CoursList: res.data.results[0].courses_list, load: false });
})
.catch((error) => {
this.setState({ error: error, load: false });
});
};
render() {
return (
<div className="course-main-feed">
<Suspense fallback={<FallBack />}>
<Switch style={{ paddingLeft: "0px" }}>
{ this.state.User && (this.state.Paid == true) ? <>
<PublicRoute restricted={false} component={Course} path="/paidcourses" handleToast={this.props.handleToast} exact/>
<PublicRoute restricted={false} component={CourseDetails} path="/paidcourses/:paidcourse_id" handleToast={this.props.handleToast} />
</>: null }
</Switch>
</Suspense>
</div>
);
}
}
export default fileone;
In the given code as we can see there is a line inside componentdidmount this.setState({ CoursList: res.data.results[0].courses_list, load: false }); in this line there are n number of courses object list. I am trying to map this courses_list in another file. I tried with the below code but I seems like the data is not getting in this
import React, { Component } from 'react'
import "./Course.scss";
export class Course extends Component {
constructor(props) {
super(props);
this.myRef = React.createRef();
this.state = {
data: [],
load: false,
error: null,
next: "",
prev: "",
menu: false,
};
}
setLoader = () => {
this.setState({ load: !this.state.load });
};
renderArticlesFeed = () => {
if (this.state.CoursList === 0)
return (
<div style={{ width: "100%", display: "flex", justifyContent: "center", color: "#f3990f" }}>
<span>No Courses to display!</span>
</div>)
return this.state.CoursList && this.state.CoursList.map((item, i) => {
return (
<div className="" style={{width: "100%", margin: "none"}} key={item.id}>
<div className="course-feed-column">
<div className="">
{item.title}
</div>
</div>
</div>
);
}
)
};
render() {
const { data, error, load } = this.state;
return (
<div>
{this.renderArticlesFeed()}
</div>
)
}
}
export default Course
I am not able to get the value of {item.id} and {item.title}. Any help from anyone will be appreciated.
I can't see from where you get the courseList in state. If you want to pass courseList from one component to another you could pass it as a prop

How to make React App to filter only one item

Following a course by Andrei Neagoie on Udemy, I'm making this robots app that displays and filters data gotten from an API. I've customized it a little bit and added a carousel feature, but now, when I hit the searchbox and try to filter it displays more than one item. I want it displaying only one item, how can I do this?
This is the problem I'm having: https://imgur.com/fsgesBs
App.js
import React, { Component } from 'react'
//import CardList from './components/CardList';
import SearchBox from './components/SearchBox';
import Splider from './components/Splider';
class App extends Component {
constructor(){
super()
this.state = {
robots: [],
searchField: ''
}
}
componentDidMount(){
fetch('https://jsonplaceholder.typicode.com/users')
.then(res => {
return res.json();
})
.then(users => {
this.setState({
robots: users
});
});
}
onSearchChange = (e) => {
this.setState({
searchField: e.target.value
});
}
render() {
const filtered = this.state.robots.filter(robot => {
return robot.name.toLowerCase().includes(this.state.searchField.toLowerCase());
});
// Main Render
return (
<div className="App tc">
<h1>RoboBros!</h1>
<SearchBox searchChange={this.onSearchChange}/>
<Splider robots={filtered}/>
{/* <CardList robots={filtered}/> */}
</div>
)
}
}
export default App
SearchBox.js
import React from 'react'
import '../index.css'
const SearchBox = ({ searchChange, searchField }) => {
return (
<div className="search-div">
<input className="search-box center" type="search" placeholder="Search Robots" onChange={searchChange}/>
<button className="search-btn">Search</button>
</div>
)
}
export default SearchBox;
Cards.js(Individual card items)
import React from 'react'
import '../styles/Cards.css';
const Cards = ({ name, id, email }) => {
return (
<div className="cards-wrapper dib br3 pa3 ma2 grow pointer">
<img className="cent" src={`https://robohash.org/${id}?set=set3`} alt="robots"/>
<div className="text">
<h3>{name}</h3>
<h4>{email}</h4>
</div>
</div>
)
}
export default Cards;
CardList.js
import React from 'react';
import Cards from './Cards';
const CardList = ({robots}) => {
const cardComponent = robots.map((robot, i) => {
return <Cards key={i} id={robots[i].id} name={robots[i].name} email={robots[i].email}/>;
})
return(
<div>
{cardComponent}
</div>
);
}
export default CardList;
Splider.js(Component that holds the Carousel/Slider library)
import React from 'react';
import { Splide, SplideSlide } from '#splidejs/react-splide';
import '#splidejs/splide/dist/css/themes/splide-sea-green.min.css';
import '../styles/Cards.css';
const Splider = ({robots}) => {
const cardSplide = robots.map((robot, i) => {
return (
<SplideSlide key={i} className="cards-wrapper dib br3 pa3 ma2">
<img src={`https://robohash.org/${robots[i].id}?set=set3`} alt="robots"/>
<h3>{robot.name}</h3>
<h4>{robot.email}</h4>
</SplideSlide>
);
});
return(
<Splide options={{
rewind: true,
width: '100%',
gap: '1rem',
perPage: 3,
perMove: 1,
focus: 'center',
type: 'loop',
easing: 'ease',
}}>
{cardSplide}
</Splide>
);
}
export default Splider;
The issue is with type: loop option:
import React from "react";
import { Splide, SplideSlide } from "#splidejs/react-splide";
import "#splidejs/splide/dist/css/themes/splide-sea-green.min.css";
import "../styles/Cards.css";
const Splider = ({ robots }) => {
return (
<Splide
options={{
rewind: true,
width: "100%",
gap: "1rem",
perPage: 3,
perMove: 1,
focus: "center",
//type: "loop",
easing: "ease"
}}
>
{robots.map((robot, i) => {
return (
<SplideSlide key={robot.id} className="cards-wrapper dib br3 pa3 ma2">
<img
src={`https://robohash.org/${robot.id}?set=set3`}
alt="robots"
/>
<h3>{robot.name}</h3>
<h4>{robot.email}</h4>
</SplideSlide>
);
})}
</Splide>
);
};
export default Splider;
This is the issue in splidejs project: https://github.com/Splidejs/splide/issues/145
It shows as fixed, so probably you need to wait for react-splide to include the fix as well in it's latest version.

I get an Error from React: Maximum update depth exceeded

I wrote my codes and i think everything is right but i get an error from react.js
Error: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.
App.js:
import React, { Component } from 'react';
import Navbar from "./component/Navbar";
import './App.css';
import Users from './component/Users';
class App extends Component {
state = {
users: [
{
id: 1,
name: "Jessie Alby",
salary: "5000",
department: "Software"
},
{
id: 2,
name: "John Tyson",
salary: "10000",
department: "Engineer"
},
{
id: 3,
name: "Billie Ashley",
salary: "6000",
department: "Doctor"
}
]
}
deleteUser =(id) => {
this.setState({
users: this.state.users.filter(user => id !== user.id)
})
}
render(){
return (
<div className="container">
<Navbar title='User App2'/>
<hr/>
<Users deleteUser={this.deleteUser()} users={this.state.users}/>
</div>
);
}
}
export default App;
User.js
import React, { Component } from 'react'
import PropTypes from 'prop-types'
class User extends Component {
state = {
isVisible : false
}
static defaultProps = {
name: "No info",
salary: "No info",
department: "No info"
}
onClickEvent= (e) =>{
this.setState({
isVisible: !this.state.isVisible
})
}
onDeleteUser = (e) => {
const {id,deleteUser} = this.props;
deleteUser(id);
}
render() {
//Destructing
const {name,department,salary} = this.props;
const {isVisible} = this.state;
return (
<div className="col-md-8 mb-4">
<div className="card">
<div className="card-header d-flex justify-content-between" style={{cursor:"pointer"}}>
<h4 className="d-inline" onClick={this.onClickEvent.bind(this)}>{name}</h4>
<i onClick={this.onDeleteUser} className="far fa-trash-alt" style={{cursor:"pointer"}}></i>
</div>
{
isVisible ? <div className="card-body">
<p className="card-text">Salary: {salary}</p>
<p className="card-text">Department: {department}</p>
</div> : null
}
</div>
</div>
)
}
}
User.propTypes = {
name: PropTypes.string.isRequired,
salary: PropTypes.string.isRequired,
department: PropTypes.string.isRequired,
deleteUser: PropTypes.func.isRequired
}
export default User;
Users.js
import React, { Component } from 'react';
import User from "./User";
import PropTypes from 'prop-types';
class Users extends Component {
render() {
const {users,deleteUser} = this.props;
return (
<div>
{
users.map(user=>{
return(
<User
key={user.id}
id={user.id}
name={user.name}
salary={user.salary}
department={user.department}
deleteUser={deleteUser}
/>
)
})
}
</div>
)
}
}
Users.propTypes = {
users: PropTypes.array.isRequired,
deleteUser: PropTypes.func.isRequired
}
export default Users;
It probably has something to do with this:
<Users deleteUser={this.deleteUser()} users={this.state.users}/>
When you put () at the end of the function what you are doing is calling it (executing it). When you want to pass it you have to do it like this:
<Users deleteUser={this.deleteUser} users={this.state.users}/>

Cannot read property 'map' of undefined in React Redux?

we are currently developing an e-commerce website using react-redux as front-end. It's working fine while passing the local json data using json-server for mock test but while real api url is passed then occur this TypeError: Cannot read property 'map' of undefined error. Please any one support me to solve this problem.
right-sidebar.jsx:
import React, { Component } from "react";
import Slider from "react-slick";
import "../common/index.scss";
import { connect } from "react-redux";
// import custom Components
import Service from "./common/service";
import BrandBlock from "./common/brand-block";
import NewProduct from "../common/new-product";
import Breadcrumb from "../common/breadcrumb";
import DetailsWithPrice from "./common/product/details-price";
import DetailsTopTabs from "./common/details-top-tabs";
import { addToCart, addToCartUnsafe, addToWishlist } from "../../actions";
import ImageZoom from "./common/product/image-zoom";
import SmallImages from "./common/product/small-image";
class RightSideBar extends Component {
constructor() {
super();
this.state = {
nav1: null,
nav2: null,
};
}
componentDidMount() {
this.setState({
nav1: this.slider1,
nav2: this.slider2,
});
}
render() {
const {
symbol,
item,
addToCart,
addToCartUnsafe,
addToWishlist,
} = this.props;
console.log(item);
var products = {
slidesToShow: 1,
slidesToScroll: 1,
dots: false,
arrows: true,
fade: true,
};
var productsnav = {
slidesToShow: 3,
swipeToSlide: true,
arrows: false,
dots: false,
focusOnSelect: true,
};
return (
<div>
{/* <Breadcrumb title={" Product / " + item.name} /> */}
{/*Section Start*/}
{item ? (
<section className="section-b-space">
<div className="collection-wrapper">
<div className="container">
<div className="row">
<div className="col-lg-9 col-sm-12 col-xs-12">
<div className="container-fluid">
<div className="row">
<div className="col-xl-12">
<div className="filter-main-btn mb-2">
<span className="filter-btn">
<i
className="fa fa-filter"
aria-hidden="true"
></i>{" "}
filter
</span>
</div>
</div>
</div>
<div className="row">
<div className="col-lg-6 product-thumbnail">
<Slider
{...products}
asNavFor={this.state.nav2}
ref={(slider) => (this.slider1 = slider)}
className="product-slick"
>
{item.variants.map((vari, index) => (
<div key={index}>
<ImageZoom
image={vari.images}
className="img-fluid image_zoom_cls-0"
/>
</div>
))}
</Slider>
<SmallImages
item={item}
settings={productsnav}
navOne={this.state.nav1}
/>
</div>
<DetailsWithPrice
symbol={symbol}
item={item}
navOne={this.state.nav1}
addToCartClicked={addToCart}
BuynowClicked={addToCartUnsafe}
addToWishlistClicked={addToWishlist}
/>
</div>
</div>
<DetailsTopTabs item={item} />
</div>
<div className="col-sm-3 collection-filter">
{/* <BrandBlock/> */}
<Service />
{/*side-bar single product slider start*/}
<NewProduct />
{/*side-bar single product slider end*/}
</div>
</div>
</div>
</div>
</section>
) : (
""
)}
{/*Section End*/}
</div>
);
}
}
const mapStateToProps = (state, ownProps) => {
let productId = ownProps.match.params.id;
return {
item: state.data.products.find((el) => el.id == productId),
symbol: state.data.symbol,
};
};
export default connect(mapStateToProps, {
addToCart,
addToCartUnsafe,
addToWishlist,
})(RightSideBar);
shop.js:
/**
* Mocking client-server processing
*/
import axios from "axios";
// import _products from './data.json'
import React, { useState, useEffect } from "react";
import store from "../store";
import { receiveProducts } from "../actions/index";
const TIMEOUT = 100;
const _products = axios
.get(`http://eversoftgroup.ddns.net:8000/apps/product/`)
.then((response) => {
return response.data;
});
const _category = axios
.get(`http://localhost:4000/categories`)
.then((response) => {
return response.data;
});
export default {
getProducts: (cb, timeout) =>
setTimeout(() => cb(_products), timeout || TIMEOUT),
getCategories: (cb, timeout) =>
setTimeout(() => cb(_category), timeout || TIMEOUT),
buyProducts: (payload, cb, timeout) =>
setTimeout(() => cb(), timeout || TIMEOUT),
};

How do I make my modal close in x seconds?

I am using ReactJS and a Bootstrap modal. I can open the modal just fine, but I would like it to close after 3 seconds.
I tried setTimeout as you can see below, but it doesn't close. I gave setTimeout a callback of handleClose, but after console logging, I can see that handleClose is not being called.
Here is the ItemDetailView Component:
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { Card, CardImg, CardText, CardBody,
CardTitle, CardSubtitle } from 'reactstrap';
import { addToCart } from '../actions/addToCartAction';
import './ItemDetailView.css';
import ItemAddedModal from './ItemAddedModal';
class ItemDetailView extends Component {
constructor(props) {
super(props);
this.state = {
modalOpen: false
}
// this.toggle = this.toggle.bind(this);
};
// toggle() {
// this.setState({
// modalOpen: !this.state.modalOpen
// });
// };
handleOpen = () => {
console.log("Cart Open", this.state.modalOpen);
this.setState({
modalOpen: true
},() => {setTimeout(this.handleClose(), 3000)});
// setTimeout(this.handleClose(), 3000);
};
handleClose = () => {
this.setState({
modalOpen: false
});
console.log('handleClose fired!')
};
addToCartHandler = () => {
this.props.addToCart(this.props.card);
console.log('addToCart++', this.props.quantity);
this.handleOpen()
// this.setState({
// modalOpen: true
// });
};
render() {
if (!this.props.title) {
return null;
}
return (
<div className="detail-view-wrapper">
<Card className="text-center detail-view-card">
{/* <CardImg top width="100%" src={"/" + this.props.img} alt={this.props.title} /> */}
<CardImg className="detail-view-img" top width="100%" src={"/" + this.props.img} alt={this.props.title} />
<CardBody>
<CardTitle className={"card-title"}>{this.props.title}</CardTitle>
<CardSubtitle>${this.props.price}</CardSubtitle>
<CardText>{this.props.description}</CardText>
{/* <SvgIcon className="cart-icon" onClick={() => this.addToCartHandler()} >
<AddShoppingCart />
</SvgIcon> */}
<button className= "add-to-cart-button" onClick={() => this.addToCartHandler()}>Add To Cart</button>
</CardBody>
</Card>
<ItemAddedModal open={this.state.modalOpen} toggle={this.toggle} />
</div>
);
}
}
const mapStateToProps = state => {
if (!state.data.cardData) {
return {
title: null,
img: null,
description: null,
price: null
}
}
const card = state.data.cardData[state.card.id]
return {
card: card,
title: card.title,
id: card.id,
img: card.img,
description: card.description,
price: card.price,
quantity: 0
};
}
export default connect(mapStateToProps, { addToCart })(ItemDetailView);
Here is the ItemAddedModal:
import React from 'react';
import { Modal, ModalHeader } from 'reactstrap';
import './ItemAddedModal.css';
class ItemAddedModal extends React.Component {
render () {
return (
<div>
<Modal className="item-added-modal" isOpen={this.props.open} toggle={this.props.toggle} className={this.props.className}>
<ModalHeader className="item-added-modal-header">
<p className="item-added-modal-p">Item Added To Cart</p>
</ModalHeader>
</Modal>
</div>
)
};
}
export default ItemAddedModal;
To perform an action after a state is set, we need to pass a callback to setState.
this.setState({
modalOpen: true
},()=>{
console.log(this.state.modalOpen);});

Categories