I am trying to build an application using react but I got an error saying "cannot read property 'image' of undefined"
Please help me if you found any issue because I am new in this framework.
The error showing up
function RenderCard({ item }) {
5 | return (
6 | <Card>
> 7 | <CardImg src={item.image} alt={item.name} />
8 | <CardBody>
9 | <CardTitle>{item.name}</CardTitle>
10 | {item.designation ? <CardSubtitle>{item.designation}</CardSubtitle> : null}
Full Code
import React from "react";
import { Card, CardImg, CardText, CardBody, CardTitle, CardSubtitle } from "reactstrap";
function RenderCard({ item }) {
return (
<Card>
<CardImg src={item.image} alt={item.name} />
<CardBody>
<CardTitle>{item.name}</CardTitle>
{item.designation ? <CardSubtitle>{item.designation}</CardSubtitle> : null}
<CardText>{item.description}</CardText>
</CardBody>
</Card>
);
}
function Home(props) {
return (
<div className="container">
<div className="row align-items-start">
<div className="col-12 col-md m-1">
<RenderCard item={props.dish} />
</div>
<div className="col-12 col-md m-1">
<RenderCard item={props.promotion} />
</div>
<div className="col-12 col-md m-1">
<RenderCard item={props.leader} />
</div>
</div>
</div>
);
}
export default Home;
And I'm importing it from another file
From my understanding there must be issue in importing the file
import React, { Component } from "react";
import Home from "./HomeComponent";
import Contact from "./ContactComponent";
import Menu from "./MenuComponents";
import Dishdetail from "./DishdetailComponent";
import Header from "./HeaderComponent";
import Footer from "./FooterComponent";
import { Dishes } from "../shared/dishes";
import { Comments } from "../shared/comments";
import { Leaders } from "../shared/leaders";
import { Promotions } from "../shared/promotions";
import { Switch, Route, Redirect } from "react-router-dom";
class Main extends Component {
constructor(props, context) {
super(props, context);
this.state = {
dishes: Dishes,
comments: Comments,
promotions: Promotions,
leaders: Leaders,
};
}
render() {
const HomePage = () => {
return (
<Home
dish={this.state.dishes.filter((dish) => dish.featured)[0]}
promo={this.state.promotions.filter((promo) => promo.featured)[0]}
leader={this.state.leaders.filter((leader) => leader.featured)[0]}
/>
);
};
const DishWithId = ({ match }) => {
return (
<Dishdetail
dish={this.state.dishes.filter((dish) => dish.id === parseInt(match.params.dishId, 10))[0]}
comments={this.state.comments.filter((comment) => comment.dishId === parseInt(match.params.dishId, 10))[0]}
/>
);
};
return (
<div>
<Header />
<Switch>
<Route path="/home" component={HomePage} />
<Route exact path="/menu" component={() => <Menu dishes={this.state.dishes} />} />
<Route path="/menu/:dishId" component={DishWithId} />
<Route exact path="/contactus" component={Contact} />
<Redirect to="/home" />
</Switch>
<Footer />
</div>
);
}
}
export default Main;
Thanks
You pass a promo prop to Home component:
<Home promo={...} />
But in Home component, you use using props.promotion which is undefined when it should be props.promo:
// don't use props.promotion, use props.promo instead
<RenderCard item={props.promo} />
Related
I got this error while i trying to route some link:
Uncaught Error: [HotAccessories] is not a Route component. All component children of Routes must be a Route or <React.Fragment>
import './App.css';
import PreNavbar from './Components/PreNavbar';
import Navbar from "./Components/Navbar.js"
import { BrowserRouter as Router,Route} from "react-router-dom"
import Slider from "./Components/Slider.js"
import Offers from "./Components/Offers.js"
import data from "./data/data.json";
import Heading from "./Components/Heading.js"
import StarProduct from "./Components/StarProduct.js"
import HotAccessoriesManu from "./Components/HotAccessoriesManu.js"
import HotAccessories from "./components/HotAccessories.js"
function App( ) {
return (
<Router>
<PreNavbar />
<Navbar />
<Slider start = {data.banner.start} />
<Offers offer={data.offer} />
<Heading text = "STAR PRODUCTS"/>
<StarProduct starProduct={data.starProduct}/>
<Heading text = "HOT ACCESSORIES" />
<HotAccessoriesManu />
<Route exact path="/music">
<HotAccessories music={data.hotAccessories.music} musicCover={data.hotAccessories.music} />
</Route>
</Router>
);
}
export default App;
Here is the HotAccessories component:
import HotItem from "./HotItemCard.js"
const HotAccessories = ({music, musicCover}) => {
return (
<div className='HotAccessories'>
<div>
<img src= {musicCover} alt="Cover" />
</div>
{/* ........2nd part */}
<div>
{music.map((item, index)=>(
<HotItem key={item.image} name={item.name} price={item.price} image={item.image} index={item.index} />
))}
</div>
</div>
)
}
export default HotAccessories;
here is HotItem component:
import React from 'react'
const HotItemCard = ({image,index,name,price}) => {
return (
<div className="HotItemCard">
<img src={image} alt={`${index} product`} />
<p>{name}</p>
<span>{price}</span>
</div>
)
}
export default HotItemCard
But in the terminal it's show me ....
webpack 5.68.0 compiled successfully in 244 ms
But i did't seen any output
Instead of
<Route exact path="/music">
<HotAccessories music={data.hotAccessories.music} musicCover={data.hotAccessories.music} />
</Route>
Try this
<Route exact path="/music" element={
<HotAccessories music={data.hotAccessories.music} musicCover={data.hotAccessories.music} />}
/>
read this section of the react router docs.
Keep in mind that all of your <Route /> elements should be children of the <Routes> component.
I'm following this Tutorial for build WhatsApp clone, but i'm using latest version of React and react-router-dom,
And whenever i'm start new conversation it should renders this component, instead of that, it renders nothing.
OpenConversation.js
import React, { useState, useCallback } from 'react'
import { Form, InputGroup, Button } from 'react-bootstrap'
import { useConversations } from '../contexts/ConversationsProvider';
export default function OpenConversation() {
const [text, setText] = useState('')
const setRef = useCallback(node => {
if (node) {
node.scrollIntoView({ smooth: true })
}
}, [])
const { sendMessage, selectedConversation } = useConversations()
function handleSubmit(e) {
e.preventDefault()
sendMessage(
selectedConversation.recipients.map(r => r.id),
text
)
setText('')
}
return (
<div className="d-flex flex-column flex-grow-1">
<div className="flex-grow-1 overflow-auto">
<div className="d-flex flex-column align-items-start justify-content-end px-3">
{selectedConversation.messages.map((message, index) => {
const lastMessage = selectedConversation.messages.length - 1 === index
return (
<div
ref={lastMessage ? setRef : null}
key={index}
className={`my-1 d-flex flex-column ${message.fromMe ? 'align-self-end align-items-end' : 'align-items-start'}`}
>
<div
className={`rounded px-2 py-1 ${message.fromMe ? 'bg-primary text-white' : 'border'}`}>
{message.text}
</div>
<div className={`text-muted small ${message.fromMe ? 'text-right' : ''}`}>
{message.fromMe ? 'You' : message.senderName}
</div>
</div>
)
})}
</div>
</div>
<Form onSubmit={handleSubmit}>
<Form.Group className="m-2">
<InputGroup>
<Form.Control
as="textarea"
required
value={text}
onChange={e => setText(e.target.value)}
style={{ height: '75px', resize: 'none' }}
/>
<InputGroup.Append>
<Button type="submit">Send</Button>
</InputGroup.Append>
</InputGroup>
</Form.Group>
</Form>
</div>
)
}
And this component is rendered on Dashboard.js
import React, { useState, useCallback } from 'react'
import { Form, InputGroup, Button } from 'react-bootstrap'
import { useConversations } from '../contexts/ConversationsProvider';
export default function OpenConversation() {
const [text, setText] = useState('')
const setRef = useCallback(node => {
if (node) {
node.scrollIntoView({ smooth: true })
}
}, [])
const { sendMessage, selectedConversation } = useConversations()
function handleSubmit(e) {
e.preventDefault()
sendMessage(
selectedConversation.recipients.map(r => r.id),
text
)
setText('')
}
return (
<div className="d-flex flex-column flex-grow-1">
<div className="flex-grow-1 overflow-auto">
<div className="d-flex flex-column align-items-start justify-content-end px-3">
{selectedConversation.messages.map((message, index) => {
const lastMessage = selectedConversation.messages.length - 1 === index
return (
<div
ref={lastMessage ? setRef : null}
key={index}
className={`my-1 d-flex flex-column ${message.fromMe ? 'align-self-end align-items-end' : 'align-items-start'}`}
>
<div
className={`rounded px-2 py-1 ${message.fromMe ? 'bg-primary text-white' : 'border'}`}>
{message.text}
</div>
<div className={`text-muted small ${message.fromMe ? 'text-right' : ''}`}>
{message.fromMe ? 'You' : message.senderName}
</div>
</div>
)
})}
</div>
</div>
<Form onSubmit={handleSubmit}>
<Form.Group className="m-2">
<InputGroup>
<Form.Control
as="textarea"
required
value={text}
onChange={e => setText(e.target.value)}
style={{ height: '75px', resize: 'none' }}
/>
<InputGroup.Append>
<Button type="submit">Send</Button>
</InputGroup.Append>
</InputGroup>
</Form.Group>
</Form>
</div>
)
}
App.js
import React from 'react'
import Login from './Login'
import useLocalStorage from '../hooks/useLocalStorage';
import Dashboard from './Dashboard'
import { ContactsProvider } from '../contexts/ContactsProvider'
import { ConversationsProvider } from '../contexts/ConversationsProvider';
import { SocketProvider } from '../contexts/SocketProvider';
import TopNavBar from './TopNavBar';
import Signup from "./Signup"
import { Container } from "react-bootstrap"
import { AuthProvider } from "../contexts/AuthContext"
import { BrowserRouter as Router, Routes, Route } from "react-router-dom"
import PrivateRoute from "./PrivateRoute"
import ForgotPassword from "./ForgotPassword"
import UpdateProfile from "./UpdateProfile"
function App() {
const [id, setId] = useLocalStorage('id', 0)
const AuthM = (
<AuthProvider>
<Router>
<TopNavBar />
<Routes>
<Route
path="/"
element={
<PrivateRoute>
<SocketProvider id={id}>
<ContactsProvider>
<ConversationsProvider id={id}>
<Dashboard id={id} />
</ConversationsProvider>
</ContactsProvider>
</SocketProvider>
</PrivateRoute>
}
>
</Route>
<Route
path="/update-profile"
element={
<PrivateRoute>
<UpdateProfile />
</PrivateRoute>
}
>
</Route>
<Route path="/signup" element={<Signup />} />
<Route path="/login" element={<Login onIdSubmit={setId} />} />
<Route path="/forgot-password" element={<ForgotPassword />} />
</Routes>
</Router>
</AuthProvider>
)
return (
AuthM
)
}
export default App;
i'm getting following error when app is trying to render OpenConversation.js
The above error occurred in the component:
at div
at http://localhost:3000/main.710ea063df9fff086c2a.hot-update.js:42187:5
at div
at http://localhost:3000/main.710ea063df9fff086c2a.hot-update.js:41901:5
at form
at http://localhost:3000/main.710ea063df9fff086c2a.hot-update.js:41543:5
at div
at OpenConversation (http://localhost:3000/main.710ea063df9fff086c2a.hot-update.js:1386:74)
at div
at Dashboard (http://localhost:3000/main.710ea063df9fff086c2a.hot-update.js:451:5)
at ConversationsProvider (http://localhost:3000/main.710ea063df9fff086c2a.hot-update.js:3292:5)
at ContactsProvider (http://localhost:3000/main.710ea063df9fff086c2a.hot-update.js:3181:5)
at SocketProvider (http://localhost:3000/main.710ea063df9fff086c2a.hot-update.js:3498:5)
at PrivateRoute (http://localhost:3000/main.710ea063df9fff086c2a.hot-update.js:1572:5)
at Routes (http://localhost:3000/main.710ea063df9fff086c2a.hot-update.js:63406:5)
at Router (http://localhost:3000/main.710ea063df9fff086c2a.hot-update.js:63339:15)
at BrowserRouter (http://localhost:3000/main.710ea063df9fff086c2a.hot-update.js:62819:5)
at AuthProvider (http://localhost:3000/main.710ea063df9fff086c2a.hot-update.js:3032:5)
at App (http://localhost:3000/main.ae1831d77cead42fa1a1.hot-update.js:56:89)
And this
Uncaught Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
Check the render method of OpenConversation.
Any idea on what happened there ? Thanks in advance.
Hope this helps to someone else,
As per #BrianThompsons comment, I found it was <InputGroup.Append> causes the error.
I'm doing the exact same tutorial, and had the same issue (and it's not the first time that I've gotten an error while copying the code - there have been some breaking updates since the video came out).
Instead of having <InputGroup.Append>, just stick the button inside the InputGroup, like so:
<Form.Group className="m-2">
<InputGroup>
<Form.Control
as="textarea"
required
value={text}
onChange={(e) => setText(e.target.value)}
style={{ height: '75px', resize: 'none' }}
/>
<Button type="submit">Send</Button>
</InputGroup>
</Form.Group>
That put the button next to the text box, as we wanted. Hope that helps.
I have my Parent App.js file where I have two child components, Products, and Cart. I am trying to pass my cart property to child Cart.js but haven't been successful.
App.js
import React,{useState} from 'react';
import {
Route,
BrowserRouter as Router,
} from 'react-router-dom';
import Cart from './components/Cart';
import Product from './components/Product';
function App() {
const [cart, setCart]= useState([]);
const addToCart=(product)=>{
console.log("addToCart button clicked",product)
setCart([...cart, {...product}])
}
return (
<Router>
<Route path="/home/"
render ={()=> < Product addToCart={addToCart}/>}
/>
<Route path="/cart/"
render ={()=> < Cart cart={cart} />}
/>
<div className="App">
</div>
</Router>
);
}
export default App;
Cart.js
import React from 'react'
export default function Cart({cart}) {
return (
<div >
hello
<div className="products" >
{cart.map((product, idx)=>(
<div key={idx}>
<h3>{product.name}</h3>
<h4>{product.cost}</h4>
<img src={product.image} alt = {product.name} />
</div>
))}
</div>
<div>
</div>
</div>
)
}
Product.js
import React,{useState} from 'react';
export default function Product({addToCart}) {
const [products]=useState([
{
name: 'iPhone',
cost : '$899.99',
image: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQB6BMWrPXA9KyTtxa6o600mjeUNJ7zSXgaNt--FDCR6YjQ4XWS5G1J3dSF5ChurfQEGxorkxYs&usqp=CAc',
},
{
name: 'Samsung',
cost : '$599.99',
image: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUGMCcF3_XBIKH5Dja-9iCkRP4CSA-CYaylQ&usqp=CAU'
}
])
return(
<div className="main-page">
<h1>Product Page </h1>
<div className="products" >
{products.map((product, idx)=>(
<div key={idx}>
<h3>{product.name}</h3>
<h4>{product.cost}</h4>
<img src={product.image} alt = {product.name} />
<button onClick={()=>addToCart(product)}
>Add to Cart</button>
</div>
))}
</div>
<div>
</div>
</div>
)
}
localhost:3000/ shows all the products but when I go to localhost:3000/cart/ I don't see my cart items. The mistake I am making I think is in the Route.
<Route path="/cart/"
render ={()=> < Cart cart={cart} />}
/>
How should I pass the cart variable from App.js to Cart.js ?
I am using Preact. I first tried preact-router then wouter for routing, but the problem still exists for one specific component. Here is the main entry where all routes defined:
import { h, Component } from 'preact';
import { Route } from "wouter-preact";
import Header from './partials/header';
import Home from './pages/home';
import News from './pages/news';
import Article from './pages/article';
export default class App extends Component {
render() {
return (
<div id="app">
<Header />
<Route path="/"><Home /> </Route> // working perfectly
<Route path="/a/:article"> <Article /> </Route> // not working
<Route path="/n/:newspaper"><News /> </Route> // working
</div>
);
}
}
and here is the simplified second component which is working perfectly :
import { h, Fragment } from 'preact';
import { Link, Route } from "wouter-preact";
import useFetch from '../../utils/ajax';
export default function News() {
const url = window.location.pathname.split('/');
const { data, loading } = useFetch(domain + '/api/v1/news/?newspaper=' + url[2]);
return (
<Fragment>
{loading ? (
// loading indicator
) : (
<main role="main">
<div className="py-5">
<div className="container">
<div className="row">
{data.results.map((nisha, index) => (
<div className="col-sm-6" key={index}>
<div className="col-md-10" >
<div className="card mb-2 shadow-lg" style={{ border: 'none' }} >
<Link href={'/a/' + nisha.slug}>
<img className="card-img-top" src={ nisha.cover_image } alt={ nisha.slug } />
</Link>
<div className="card-body">
// body
<div className="card-footer text-muted">
// footer
</div>
</div>
</div>
</div>
</div>
))}
</div>
</div>
</div>
</main>
)}
</Fragment>
);
}
and finally the problematic component, when I click any link from previous component, browser url changing but the component is not loading (there is no debug console message in browser console).
export default function Article() {
console.log("loaded");
return (
<div className="main">
<div className="py-5">
<div className="column">
<div>example article</div>
</div>
</div>
</div>
);
}
I am making an advertising website with reusable components that load with different graphics depending on what page it is. I am using react-router-dom Route exact path. I imagine i need to be able to read the state of that with my useEffect,[]. So how do i pass down the state so its able to be read by the component.
Please note that the component Hero appears in the functions for Home, Consultants and Solutions
const Hero = props => {
useEffect(() => {
console.log(props);
}, []);
return (
<Fragment>
<div className='grid-hero'>
<Fragment>
<div className='overlay'>
<div>
<p className='bg-dark'></p>
<img src={{ homeimg } || { consimg } || { solsimg }} alt='' />
</div>
</div>
</Fragment>
<Router>
<Fragment>
<Navbar />
<Switch>
<Route exact path='/' component={Home} />
<Route exact path='/consultants' component={Consultants} />
<Route exact path='/solutions' component={Solutions} />
<Route exact path='/contactus' component={ContactUs} />"
</Switch>
</Fragment>
</Router>
<div
className={
{pathname === "/" && ("grid-home")}
{pathname === "/consultants" && ("grid-consultants")}
{pathname === "/solutions" && ("grid-solutions")}
}>
maybe this is what you're looking for:
I've added Hero as top-level image component where your image would switch. I don't have the images, so I used strings, but if you import images like JSX, you'll be able to use this code by removing the img strings inside my Hero dummy component.
adding reference image import syntax for help:
import img from './img.png';
complete example:
import React, { Fragment } from "react";
import {
BrowserRouter as Router,
Route,
Link,
useLocation
} from "react-router-dom";
function BasicExample() {
return (
<Router>
<div>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/contactus">ContactUs</Link>
</li>
<li>
<Link to="/solutions">Solutions</Link>
</li>
</ul>
<hr />
<Hero />
<Route exact path="/" component={Home} />
<Route path="/contactus" component={ContactUs} />
<Route path="/solutions" component={Solutions} />
</div>
</Router>
);
}
const Hero = () => {
const homeimg = "HOME_IMAGE";
const consimg = "CONTACT_US_IMAGE";
const solsimg = "SOLUTIONS_IMAGE";
let img = null;
const location = useLocation();
if (location.pathname === "/") img = homeimg;
else if (location.pathname === "/contactus") img = consimg;
else if (location.pathname === "/solutions") img = solsimg;
return (
<Fragment>
<h3>{location.pathname}</h3>
<div className="grid-hero">
<Fragment>
<div className="overlay">
<div>
<p className="bg-dark" />
{img}
</div>
</div>
</Fragment>
</div>
</Fragment>
);
};
function Home() {
return (
<div>
<h2>Home</h2>
</div>
);
}
function ContactUs() {
return (
<div>
<h2>ContactUs</h2>
</div>
);
}
function Solutions() {
return (
<div>
<h2>Solutions</h2>
</div>
);
}
export default BasicExample;
codepen-link