Click on Link to show details of item - ReactJs, Node.js - javascript

App is running on Node.js and React. In database (mongodb used) I have collection Rooms that contains details about particular room.
On LandingPage I display some of room details and to se more person has to click on View link.
LandingPage.js
const Room = props => (
<div className = "col-md-4" >
<div className="card mb-4 shadow-sm">
<img src={props.room.imageData} class="card-img-top" alt="..." width="100%" height="225" />
<div className="card-body">
<h5 class="card-title">{props.room.title}</h5>
<p className="card-text">{props.room.description}</p>
<div className="d-flex justify-content-between align-items-center">
<div className="btn-group">
<Link className="btn btn-sm btn-outline-secondary" to={"/view/"+props.room._id}>View</Link>
</div>
</div>
</div>
</div>
</div >
)
Link is sending me to view page
<Link className="btn btn-sm btn-outline-secondary" to={"/view/"+props.room._id}>View</Link>
But I am not sure how would I display now all details of room from database?
View.js
export default class RoomsAdmin extends React.Component {
constructor(props) {
super(props);
this.state = { rooms: [] };
}
componentDidMount() {
axios.get('http://localhost:3090/admin/')
.then(response => {
this.setState({
rooms: response.data
})
.catch(function (error) {
console.log(error);
})
})
}
roomList() {
return this.state.rooms.map(function (currentRoom, i) {
return <Room room={currentRoom} key={i} />
});
}
render() {
console.log(this.props);
return (
<div>
<div className="album py-5 bg-light">
<div className="container">
<div className="row">
<div className="col-md-4">
<div className="card mb-4 shadow-sm">
<img src={props.room.imageData} className="card-img-top" alt="..." width="100%" height="225" />
<div className="card-body">
<h5 class="card-title">{props.room.title}</h5>
<p className="card-text">{props.room.description}</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
)
}
}
I came up with this code for now but I am getting following error:
Uncaught ReferenceError: props is not defined

Yes because you are writing props not this.props in your image tag.
In RoomAdmin Component
<img src={props.room.imageData} className="..../>
Use this instead
<img src={this.props.room.imageData} className=".../>

Related

How can I call array data in a useEffect - ReactJS

I am trying to fetch the weather data of a farm with latitude and longitude coordinates. I have successfully managed to get the farm data from the Api to a React Component. And now I want to fetch the weather data of the farm using its coordinates. I am using openweathermap
But the Problem is, I keep getting this error: GET http://api.openweathermap.org/data/2.5/weather?lat=undefined&lon=undefined&appid=[API]&units=metric 400 (Bad Request)
Someone please help
Here is the Farm Component
import React, { useState, useEffect } from "react";
import { Link, useNavigate, useParams } from "react-router-dom";
import Menubar from "../../components/menubar/Menubar";
import Skeleton from "react-loading-skeleton";
import toast, { Toaster } from 'react-hot-toast';
import axios from 'axios';
import { LazyLoadImage } from "react-lazy-load-image-component";
import Weather from "../../components/weather/Weather";
import FarmWeather from "../../components/weather/FarmWeather";
function FarmDetails() {
let navigate = useNavigate();
const [farm, setFarm] = useState('');
const { username } = useParams();
const { farmId } = useParams();
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
let isMounted = true;
axios.get(`/api/farm/${username}/${farmId}`).then(res => {
if (isMounted) {
if (res.data.status === 200) {
setFarm(res.data.farm);
setIsLoading(false);
console.warn(res.data.farm)
}
else if (res.data.status === 404) {
navigate('/');
toast.error(res.data.message, "error");
}
}
});
return () => {
isMounted = false
};
}, []);
return (
<div>
<Menubar />
<div className="appHeader bg-primary text-light">
<div className="left">
<a onClick={() => navigate(-1)} className="headerButton goBack">
<i className="fi fi-rr-angle-left"></i> </a>
</div>
<div className="pageTitle">{farm.farmname}</div>
<div className="right"></div>
</div>
<div id="appCapsule">
<div className="section mt-3 mb-3">
<div className="card">
<div className="card-header">
Discover
</div>
<div className="card-body">
<h5 className="card-title">Farm Supplies</h5>
<p className="card-text">Order for farm supplies suitable for your farm and grow healthy fruits</p>
Go to Shop
</div>
</div>
</div>
<FarmWeather farm={farm} />
<div className="section mt-3 mb-3">
<div className="row">
<div className="col-6">
<div className="card card-normal">
<div className="card-body">
<h5 className="card-title title-small mb-2">Location</h5>
<div className="card-icon mb-0">
<i className="fi fi-rr-marker"></i>
</div>
</div>
</div>
</div>
<div className="col-6">
<div className="card card-normal card-add">
<a href="farm-fruits.php?view=<?php echo $row['farmid']; ?>">
<div className="card-body">
<h5 className="card-title title-small mb-2">Fruits</h5>
<div className="card-icon mb-0">
<i className="fi fi-rr-apple-whole"></i>
</div>
</div>
</a>
</div>
</div>
<div className="col-6">
<div className="card card-normal">
<div className="card-body">
<h5 className="card-title title-small mb-2">Sales</h5>
<div className="card-icon mb-0">
<i className="fi fi-rr-bolt"></i>
</div>
</div>
</div>
</div>
<div className="col-6">
<div className="card card-normal">
<div className="card-body">
<h5 className="card-title title-small mb-2">Expenses</h5>
<div className="card-icon mb-0">
<i className="fi fi-rr-settings"></i>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
export default FarmDetails;
And the Weather Component
import React, { useState, useEffect } from "react";
const FarmWeather = ({ farm }) => {
const [weather, setWeather] = useState({});
useEffect(() => {
fetch(`//api.openweathermap.org/data/2.5/weather?lat=${farm.latitude}&lon=${farm.longitude}&appid=[API]&units=metric`)
.then((result) => result.json())
.then((weather) => {
setWeather(weather);
});
}, []);
console.warn("result", weather)
return (
<div className="section mt-3 mb-3">
<div className="card text-white bg-primary mb-2">
<div className="card-header">Weather in <span>{weather.name}</span>
<div className="weather-icon">
<img src={`http://openweathermap.org/img/w/${weather.weather && weather.weather[0].icon}.png`} alt="weather icon" />
</div>
</div>
<div className="card-body">
<h5 className="card-title">Temp <span>{weather.main && weather.main.temp} °C</span></h5>
<p className="card-text">Our Technologies have discovered that the Current Weather around your Farm in {farm.county && farm.county.countyname} is
Mostly
<span id="description" ></span>
</p>
</div>
</div>
</div>
);
}
export default FarmWeather;
You need to check that farm is defined before making the api call, you can put it as a dependency.
useEffect(() => {
if (farm) fetch(`//api.openweathermap.org/data/2.5/weather?lat=${farm.latitude}&lon=${farm.longitude}&appid=[API]&units=metric`)
.then((result) => result.json())
.then((weather) => {
setWeather(weather);
});
}, [farm]);

Change boolean value onClick in React

I'm trying to change the value of a boolean from an object imported from a JSON file in React. I want the offers.availability value to change to false after clicking on the "add to cart" button.
Here's my code:
function App() {
class App {
constructor () {
this.state = {
offers: [],
}
this.handleToggle = this.handleToggle.bind(this);
}
componentDidMount() {
this.state.setState({ offers: Data });
}
handleToggle (offers) {
this.setState(prevState => ({
offers: prevState.offers.map(prevOffer => {
if (prevOffer.availability === offers.availability) {
return {
availability: prevOffer.availability,
isTrue: !prevOffer.isTrue
}
}
return prevOffer;
})}));
}
}
return (
<div className="container">
<div className="row">
{Data.offers.map(offers => {
return(
<div key={offers.make + offers.model + offers.engine + offers.photo} className="col-sm-4">
<div className="card" >
<img src={offers.photo} className="card-img-top" alt={offers.make + ' ' + offers.model } width="100%"/>
<div className="card-body pt-0 px-0">
<div className="d-flex flex-row justify-content-between mb-0 px-3 p-3 mid">
<div className="d-flex flex-column">
<h4>{offers.make} {offers.model}</h4>
</div>
<div className="d-flex flex-column">
<button type="button" className="btn btndelete"><FaTrash /></button>
</div>
</div>
<div className="d-flex flex-row justify-content-between px-3">
<div className="d-flex flex-column"><span className="text-muted">Engine: {offers.engine}</span></div>
<div className="d-flex flex-column">
{offers.availability.toString()}
</div>
</div>
<div className="mx-3 mt-3 mb-2 d-grid gap-2">
{offers.availability
? <button type="button" className="btn btn-primary addtocartbtn" onClick={() => Data.offers.handleToggle(offers)}>
<small>Add to cart</small>
</button>
: <button type="button" className="btn btn-disabled" onClick={console.log('???')}><small>Currently unavailabe</small></button>
}
</div>
</div>
</div>
</div>
)
}) }
</div>
</div>
)}
export default App;
I tried to toggle the boolean value but I currently get a ".offers.handleToggle is not a function" error after clicking.
I'm new to this so please don't judge if I did something really stupid here :) What could be the possible solution to this?
You should not use Data.offers.handleToggle. From what I see, Data.offers is an array of objects which they don't have a function handleToggle defined.
However, you are defining a function handleToggle on the App component that looks good. It should work if you change onClick={() => Data.offers.handleToggle(offers)} with either onClick={() => handleToggle(offers)} or onClick={() => this.handleToggle(offers)}
UPDATE
After running your code I saw the component is defined as a mix of a functional component and a class component. First, decide what you are going to use and then fix the errors 1 by 1. The constructor for example is missing the props, there are onclicks that are not well defined and a few more things.
Here is your code if used as a class component.
import { Component } from "react";
export class App extends Component<{}, { offers: any[] }> {
constructor(props: {}) {
super(props);
this.state = {
offers: [],
};
this.handleToggle = this.handleToggle.bind(this);
}
componentDidMount() {
this.setState({ offers: Data });
}
handleToggle(offers: any) {
this.setState((prevState) => ({
offers: prevState.offers.map((prevOffer) => {
if (prevOffer.availability === offers.availability) {
return {
availability: prevOffer.availability,
isTrue: !prevOffer.isTrue,
};
}
return prevOffer;
}),
}));
}
render() {
return (
<div className="container">
<div className="row">
{this.state.offers.map((offers) => {
return (
<div
key={offers.make + offers.model + offers.engine + offers.photo}
className="col-sm-4"
>
<div className="card">
<img
src={offers.photo}
className="card-img-top"
alt={offers.make + " " + offers.model}
width="100%"
/>
<div className="card-body pt-0 px-0">
<div className="d-flex flex-row justify-content-between mb-0 px-3 p-3 mid">
<div className="d-flex flex-column">
<h4>
{offers.make} {offers.model}
</h4>
</div>
<div className="d-flex flex-column">
<button type="button" className="btn btndelete">
<FaTrash />
</button>
</div>
</div>
<div className="d-flex flex-row justify-content-between px-3">
<div className="d-flex flex-column">
<span className="text-muted">
Engine: {offers.engine}
</span>
</div>
<div className="d-flex flex-column">
{offers.availability.toString()}
</div>
</div>
<div className="mx-3 mt-3 mb-2 d-grid gap-2">
{offers.availability ? (
<button
type="button"
className="btn btn-primary addtocartbtn"
onClick={() => this.handleToggle(offers)}
>
<small>Add to cart</small>
</button>
) : (
<button
type="button"
className="btn btn-disabled"
onClick={() => console.log("???")}
>
<small>Currently unavailabe</small>
</button>
)}
</div>
</div>
</div>
</div>
);
})}
</div>
</div>
);
}
}
You just need to define the offers type and a FaTrash component

Uncaught TypeError: Cannot read property 'renderRows' of undefined

I am in the process of switching a component class to a function in my website so I can use hooks to interact with my backend, but after switching to the arrow function i am now getting the error above. What exactly changed to cause this error, I know i had to delete the render{} but is that what is causing it? Here is my current code where the error is located.
import React, { Component, useEffect, useState } from "react";
import ReactDOM from 'react-dom';
import { Link } from "react-router-dom";
import "./HomePageBody.scss";
import products from "../../../../back-end/products";
const HomePageBody = () => {
const getProducts = async() => {
try {
const response = await fetch("http://localhost:5000/carts");
const jsonData = await response.json();
console.log(jsonData);
} catch (err) {
console.error(err.message);
}
}
useEffect(() => {
getProducts();
});
let renderRows = () => {
let finalArr = [];
products.forEach((product) => {
finalArr.push(
<div className="col-md-6 col-lg-4 mt-4 colCard w-75">
<Link
to={{
pathname: "/ProductPage/" + product.name,
state: { sentproduct: product },
}}
>
<div className="card w-100 h-100">
<div className="card-img-wrap w-100 h-100">
<img
className=" card-img-top"
src={product.img}
alt="Card image cap"
/>
</div>
<div className="card-body">
<h6 className="card-title text-center">{product.name}</h6>
<p className="card-text text-center">
<small className="text-muted red">${product.price}</small>
</p>
</div>
</div>
</Link>
</div>
);
});
return finalArr;
}
return (
<div className="largebody ">
<div
id="carouselAd"
className="carousel slide carousel-custom"
data-ride="carousel"
>
<div className="carousel-inner">
<div className="carousel-item active">
<a href="#">
<img
className=""
src="https://res.cloudinary.com/ndc-images/image/upload/f_auto,fl_force_strip.preserve_transparency.progressive.sanitize,q_auto:best/media//blog/buy-affordable-high-quality-clothes-that-last-from-sustainable-brands.jpg"
alt="First slide"
/>
</a>
</div>
<div className="carousel-item">
<a href="#">
<img
className=""
src="https://res.cloudinary.com/ndc-images/image/upload/f_auto,fl_force_strip.preserve_transparency.progressive.sanitize,q_auto:best/media//blog/buy-affordable-high-quality-clothes-that-last-from-sustainable-brands.jpg"
alt="Second slide"
/>
</a>
</div>
<div className="carousel-item">
<a href="#">
<img
className=""
src="https://res.cloudinary.com/ndc-images/image/upload/f_auto,fl_force_strip.preserve_transparency.progressive.sanitize,q_auto:best/media//blog/buy-affordable-high-quality-clothes-that-last-from-sustainable-brands.jpg"
alt="Third slide"
/>
</a>
</div>
<div className="carsouselControls">
<a
className="carousel-control-prev"
href="#carouselAd"
role="button"
data-slide="prev"
>
<span
className="carousel-control-prev-icon"
aria-hidden="true"
></span>
<span className="sr-only">Previous</span>
</a>
<a
className="carousel-control-next"
href="#carouselAd"
role="button"
data-slide="next"
>
<span
className="carousel-control-next-icon color.red"
aria-hidden="true"
></span>
<span className="sr-only">Next</span>
</a>
</div>
</div>
</div>
<div className="col-lg-9 col-sm-12 m-auto">
<h1 className="text-center mt-5 mb-3 ml-auto mr-auto headerFont">
"Equality is the soul of liberty; there is, in fact, no liberty
without it." - Frances Wright
</h1>
<p className="paragraphFont">
We at EqualityFits believe that all people should be treated equaly
and fairly regarldess of race, religion, and sexuality. We support
groups such as Black Lives Matter and LBGTQ. Every one of our
products donates to an underlying organization that has to do with
that specific product. We believe that helping theses organizations
is a first step in total equality throughout society.
</p>
</div>
<div className="container cardbuttons text-center mb-5 mt-5">
<div className="row mt-5 inline-block">
<div className="col-lg-4 ml-auto">
<Link
to={{
pathname: "/Collections/" + "LGBT",
key: Math.random,
state: { sentinfo: "LGBT" },
}}
>
<div className="card">
<div className="card-img-wrap">
<img
className="card-img-top ml-auto mt-2 img"
src="http://equalityfits.com/img/menstshirt.png"
alt="Card image cap"
/>
</div>
</div>
</Link>
</div>
<div className="col-lg-4 ">
<Link
to={{
pathname: "/Collections/" + "LGBT",
key: Math.random,
state: { sentinfo: "LGBT", name: false, cat: true },
}}
>
<div className="card position-relative">
<div className="card-img-wrap right">
<img
className="card-img-top ml-auto mt-2 img"
src="http://equalityfits.com/img/menstshirt.png"
alt="Card image cap"
></img>
</div>
</div>
</Link>
</div>
<div className="col-lg-4 mr-auto">
<Link
to={{
pathname: "/Collections/" + "LGBT",
key: Math.random,
state: { sentinfo: "LGBT", name: false, cat: true },
}}
>
<div className="card">
<div className="card-img-wrap">
<img
className="card-img-top mr-auto mt-2 img"
src="http://equalityfits.com/img/womenstshirt.png"
alt="Card image cap"
/>
</div>
</div>
</Link>
</div>
</div>
</div>
<div className="row ml-auto mr-auto mt-5 w-75">
<div className="col-lg-9 col-sm-12 m-auto p-0 mt-5">
<h1
className="text-center font-weight-bold mt-5"
style={{ marginLeft: "9px" }}
>
Best Selling
</h1>
<hr style={{ borderTop: "3px solid rgba(0, 0, 0, 0.1)" }}></hr>
<div className="row justify-content-center">
**{this.renderRows()}** <-----------------Where i call upon the function
</div>
</div>
</div>
</div>
);
}
export default HomePageBody;
I call upon the function at the bottom, i put arrows next to it to make it easier.
You are no longer in a class, so the this context no longer makes sense. Just change it to renderRows().
renderRows is no longer a method on you class, but rather a function in your component. Therefore instead of this.renderRows(), you call it using renderRows().

How can I call a function inside of a .map of arrays?

I am passing down a function through props that capitalizes a few items being mapped over. I am getting an error on the item portion of item.creator.I am just wondering why I am recieving the error and not able to just call the function inside of the map. Thanks for your help.
Error message is Line Parsing error: Unexpected token, expected ",".
PARENT COMPONENT
export default function MainContent() {
const techContent = useSelector(displayTechContent);
const designContent = useSelector(displayDesignContent);
const makeCapital = (words) => words.replace(/^\w/, (c) => c.toUpperCase());
return (
<div className="container">
<div className="topics-list">
<div className="topic-row mb-5">
<h2 className="topic-heading mb-4">Software Development</h2>
<ContentCard data={techContent} capitalize={makeCapital} />
</div>
CHILD COMPONENT
export default (props) => (
<div>
<div className="resource-list">
{props.data.map((item) => (
<a key={item.id} href={item.link} className="resource-card-link mr-3">
<div className="card resource-card mb-2">
<div className="card-header">
<h4 className="resource-title">{item.title}</h4>
<span className="resource-creator">by: ***{props.capitalize({item.creator})}***.</span> <--this function
</div>
<div className="card-body py-3">
<div className="resource-description mb-2">
{item.description}
</div>
<div className="resource-type mb-2">
<i className="fas fa-book"></i> {item.type}
</div>
The curly braces around of item.creator are redundant.
export default (props) => (
<div>
<div className="resource-list">
{props.data.map((item) => (
<a key={item.id} href={item.link} className="resource-card-link mr-3">
<div className="card resource-card mb-2">
<div className="card-header">
<h4 className="resource-title">{item.title}</h4>
<span className="resource-creator">by: ***{props.capitalize(item.creator)}***.</span> <--this function
</div>
<div className="card-body py-3">
<div className="resource-description mb-2">
{item.description}
</div>
<div className="resource-type mb-2">
<i className="fas fa-book"></i> {item.type}
</div>

Refactoring jQuery for react component

I am moving away from using jQuery to do some quick hides, shows and css changes because I am using components in react that need to be re-rendered and thus are not triggering the jQuery actions that need a page refresh. I think my issue is that I need to set the state in each component but I am a bit confused as to how. Here is an example of the jquery for this particular view:
<script type="text/javascript">
$(document).ready(function () {
$(".schedule-times").hide();
$(".final-check").hide();
$(".available-time").on('click', function () {
$(".schedule-times").toggle();
});
$(".schedule-button").on('click', function () {
$('.finalize-timeline').css("background", "#4CAF50");
$(".final-check").show();
});
});
</script>
Here is an example of a component I have written:
import React, { Component } from 'react';
import '../../App.css';
import Calendar from '../Calendar';
import { Link } from 'react-router';
class Schedule_3 extends Component {
render() {
return (
<div className="wow fadeIn">
<div className="container">
<div className="timeline">
<div className="col-md-12 offset-md-2">
<div className="row">
<div className="col-md-2 timeline-box">
<div className="timeline-badge active-timeline">
<i className="fa fa-check wow bounceInDown"></i>
</div>
<span>How do you want to schedule?</span>
</div>
<div className="col-md-2 timeline-box">
<div className="timeline-badge active-timeline">
<i className="fa fa-check wow bounceInDown"></i>
</div>
<span>Pick your lesson type</span>
</div>
<div className="col-md-2 timeline-box">
<div className="timeline-badge active-timeline">
</div>
<span>Find a time</span>
</div>
<div className="col-md-2 timeline-box">
<div className="timeline-badge" id="no_border">
</div>
<span>Finalize</span>
</div>
</div>
</div>
</div>
<div className="row">
<div className="container">
<div className="col-md-6 offset-md-3">
<Calendar />
</div>
</div>
</div><br />
<div className="row schedule-times">
<div className="col-md-12 offset-md-2">
<div className="row">
<div className="col-md-4 offset-md-1">
<i className="fa fa-clock"></i>
10:30AM
</div>
<div className="col-md-2 offset-md-1">
<Link to="Schedule_4">
<button className="btn btn-primary">
Book Now
</button>
</Link>
</div>
</div><br />
<div className="row">
<div className="col-md-4 offset-md-1">
<i className="fa fa-clock"></i>
11:00AM
</div>
<div className="col-md-2 offset-md-1">
<button className="btn btn-primary">
Book Now
</button>
</div>
</div><br />
<div className="row">
<div className="col-md-4 offset-md-1">
<i className="fa fa-clock"></i>
11:30AM
</div>
<div className="col-md-2 offset-md-1">
<button className="btn btn-primary">
Book Now
</button>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
}
export default Schedule_3;
Looking at your code I would suggest the first thing you need to do is split it into smaller, more manageable and more readable components that are responsible for 1 thing.
As you have posted a big example I cannot show you how to do it for every case you have, but I can give you a simple example that can be adapted for your use cases.
class ToggleContent extends React.Component {
constructor() {
super();
this.state = { hidden: true };
this.toggleContent = this.toggleContent.bind(this);
}
toggleContent() {
this.setState(prevState => ({
hidden: !prevState.hidden
}));
}
render() {
const { hidden } = this.state;
const { children } = this.props;
return (
<div>
<button onClick={ this.toggleContent }>Toggle</button>
<div>
{ !hidden && children }
</div>
</div>
);
}
}
You can use this component like this <ToggleContent>Hello World</ToggleContent> and it will toggle visibility of Hello World on the button press. You can put anything inside of this, including other components, it doesn't have to just be text.
You can see an example of it running here.
You can see the state of whether the children are hidden or not is held in the component this.state = { hidden: true };.
The children are then rendered if it is not hidden, if !hidden === true. We can see that inline here { !hidden && children }.
The toggleContent method is then using the previous state to switch back and forth between hidden and showing.
toggleContent() {
this.setState(prevState => ({
hidden: !prevState.hidden
}));
}

Categories

Resources