React, availableForSale: true to display Text when true - reactjs

I am using Shopify as my backend and react as my frontend, and when the product.availableforsale is true I want it to print out in stock. Here is the code on my product page.
I have commented on the code where the {product.availableForSale} is in the product page component.
import React, { useEffect, useContext, useState } from "react";
import { useParams } from "react-router-dom";
import { ShopContext } from "../../context/shopContext";
import { Text, Div, Button, Row, Col, Container, Image } from "atomize";
import { Link } from "react-router-dom";
import "./ProductPage.css";
import { Spinner } from 'react-bootstrap';
//Res
// const theme = {
// grid: {
// colCount: 8,
// gutterWidth: 0
// }
// };
const ProductPage = () => {
let { id } = useParams();
const { fetchProductWithId, addItemToCheckout, product, client } = useContext(
ShopContext
);
//Fav
const [favoriteText, setFavoriteText] = useState("Add to Favorite");
//Variants
const [sizeIndex, setSizeIndex] = useState('');
const [posterIndex, setPosterIndex] = useState('');
useEffect(() => {
fetchProductWithId(id);
return () => {};
}, [fetchProductWithId, id]);
if (!product.title) return <div className="prod-spinner-container"><Spinner animation="border" variant="primary" /></div>
//Variants
const selectedVariant = client.product.helpers.variantForOptions(product, {
Size: sizeIndex || product.options[0].values[0].value,
Poster: posterIndex || product.options[1].values[0].value
});
return (
<Container>
<div className={"row"} >
<Div className="prod-img" p="1.5rem">
<Image src={product.images[0].src} w="20rem" p="2rem"/>
</Div>
<div className="prod-size col-12 col-sm-6 " pos="Center" key={product.id}>
<Text className="title-txt"tag="h1" textColor="white" textWeight="500" m={{ y: "2rem" }} >
{product.title}
</Text>
<Text className="title-txt"tag="h1" textColor="white" textWeight="500" m={{ y: "2rem" }} >
{/* Print Out text? */}
{product.availableForSale}
{product.vendor}
</Text>
{/* Selected variant will allow the price to change due to frame size etc */}
<Text className="cost-txt" tag="h3" textColor="white" m={{ y: "2rem" }} textWeight="100">
Price € {selectedVariant?.price} Excl Shipping
</Text>
{/* Poster size */}
<Text>Size (inc)</Text>
<select className="custom-select" value={posterIndex} onChange={e => setPosterIndex(e.target.value)} >
{product.options[1].values.map((item, index) => (
<option value={item.value}>{item.value}</option>
))
}
</select>
<Text>Frame</Text>
<select className="custom-select" value={sizeIndex} onChange={e => setSizeIndex(e.target.value)} >
{product.options[0].values.map((item, index) => (
<option value={item.value}>{item.value}</option>
))
}
</select>
<Button
rounded="lg"
shadow="3"
bg="black500"
m={{ y: "2rem" }}
onClick={() => addItemToCheckout(selectedVariant?.id, 1)}
>
Add to Cart
</Button>
<Button rounded="lg"
shadow="3"
bg="black500"
m={{ y: "2rem" }}
onClick={() => {
// console.log(product);
let favorites = JSON.parse(localStorage.getItem('favorites') || "[]");
const productExists = favorites.find(favorite => favorite.id === product.id);
if(productExists) {
favorites = favorites.filter(favorite => favorite.id !== product.id);
setFavoriteText("Add to Favorite")
localStorage.setItem('favorites', JSON.stringify(favorites));
} else {
favorites = [...favorites, product];
setFavoriteText("Remove from Favorite");
localStorage.setItem('favorites', JSON.stringify(favorites));
}
}}>
{/* <HeartIcon title="Add to Favourites" style={{height: '25px', width: '25px', backgroundColor: "#fff", color: "red" }} /> */}
{favoriteText}
</Button>
</div>
</div>
</Container>
);
};
export default ProductPage;
Any help would be greatly appreciated thanks. Please let me know if more code is needed thanks

If you want only one condition to show Out in Stock then use this
{product.availableForSale &&
<Text className="title-txt"tag="h1" textColor="white" textWeight="500" m={{ y: "2rem" }} >
{/* Print Out text? */}
{product.vendor}
</Text>
}
Or
{product.availableForSale ?
<Text className="title-txt"tag="h1" textColor="white" textWeight="500" m={{ y: "2rem" }} >
{/* Print Out text? */}
{product.vendor}
</Text>
:<div>Available</div>
}

You can create another state to track the download from the server
[isLoading, setIsLoading] = useState(true)
and when displaying data, look at this state
{
!isLoading ? (
<Text
className="title-txt"
tag="h1"
textColor="white"
textWeight="500"
m={{ y: "2rem" }}
>
{/* Print Out text? */}
{product.vendor}
</Text>
) : (
<Loader />
);
}

Related

React fetch - initial state not loading - what can I do?

I have started to learn react two days ago, so I am a complete newbie. I am attempting to create a simple website app that loads beer data (image, name, tagline) from a public API on cards. Upon clicking on the card, it should display description, name, tagline.
My problem is that upon initial load, no data loads - each card only loads after I click on it.after clicking one card twice
It was working fine before I introduced the clicking function and backFacingCard.
I tried several things, including making separate components for each card side but like I said, I am still very new to react and coding in general, so I am not sure if what I do is correct. I would be very grateful for any tips and tricks.
Here is my code for the card component:
const BeerTile = (props) => {
const frontFacingCard = {
src: (
<Card
hoverable
size="small"
style={{
width: 350,
height: 220,
}}
cover={
<img
className="beer_tile_card_img"
alt="beer-bottle"
src={props.beer?.image_url}
/>
}
>
<Meta
className="meta"
title={props.beer?.name}
description={props.beer?.tagline}
/>
</Card>
),
};
const backFacingCard = {
src: (
<Card
hoverable
size="small"
style={{
width: 350,
height: 220,
}}
cover={
<div className="beer-description">{props.beer?.description}</div>
}
>
<Meta
className="meta"
title={props.beer?.name}
description={props.beer?.tagline}
/>
</Card>
),
};
const [card, setCard] = useState(frontFacingCard.src);
const [showsFront, setShowsFront] = useState(true);
const clickHandler = () => {
if (showsFront) {
setCard(backFacingCard.src);
setShowsFront(false);
props.frontSide(showsFront);
} else {
setCard(frontFacingCard.src);
setShowsFront(true);
props.frontSide(showsFront);
}
};
return (
<div
className="beer_tile_card"
onClick={clickHandler}
front={showsFront ? 1 : 0}
>
{card}
</div>
);
};
in your second component you can use useEffect
const [card, setCard] = useState(frontFacingCard.src);
const [showsFront, setShowsFront] = useState(true);
useEffect(()=>{
console.log("frontFacingCard.src",frontFacingCard.src)//check if source is available
setCard(frontFacingCard.src)
},[frontFacingCard.src])
const clickHandler = () => {
if (showsFront) {
setCard(backFacingCard.src);
setShowsFront(false);
props.frontSide(showsFront);
} else {
setCard(frontFacingCard.src);
setShowsFront(true);
props.frontSide(showsFront);
}
};
return (
<div
className="beer_tile_card"
onClick={clickHandler}
front={showsFront ? 1 : 0}
>
{card}
</div>
);
};
you can do this alternate solution
const BeerTile = (props) => {
const FrontFacingCard = () => {
return (
<Card
hoverable
size="small"
style={{
width: 350,
height: 220,
}}
cover={
<img
className="beer_tile_card_img"
alt="beer-bottle"
src={props.beer?.image_url}
/>
}
>
<Meta
className="meta"
title={props.beer?.name}
description={props.beer?.tagline}
/>
</Card>
)
};
const BackFacingCard =()=> {
return (
<Card
hoverable
size="small"
style={{
width: 350,
height: 220,
}}
cover={
<div className="beer-description">{props.beer?.description}</div>
}
>
<Meta
className="meta"
title={props.beer?.name}
description={props.beer?.tagline}
/>
</Card>
)
};
const [showsFront, setShowsFront] = useState(true);
const clickHandler = () => {
setShowsFront(!showFront);
props.frontSide(showsFront);
};
return (
<div
className="beer_tile_card"
onClick={clickHandler}
front={showsFront ? 1 : 0}
>
{
showsFront
? <FrontFacingCard />
: <BackFacingCard />
}
</div>
);
};
Checkout this cleaner solution, that separate back,front and Tile.
const BeerTile = (props) => {
const [front, setFront] = useState(true);
const clickHandler = () => {
setFront(!front)
};
return (
<div
className="beer_tile_card"
onClick={clickHandler}
front={showsFront ? 1 : 0}
>
{front?<FrontFacingCard {...props}/>:<BackFacingCard {...props}/> }
</div>
);
};
const FrontFacingCard=(props)=>
(
<Card
hoverable
size="small"
style={{
width: 350,
height: 220,
}}
cover={
<img
className="beer_tile_card_img"
alt="beer-bottle"
src={props.beer?.image_url}
/>
}
>
<Meta
className="meta"
title={props.beer?.name}
description={props.beer?.tagline}
/>
</Card>
),
};
const BackFacingCard =( props)=>(
<Card
hoverable
size="small"
style={{
width: 350,
height: 220,
}}
cover={
<div className="beer-description">{props.beer?.description}</div>
}
>
<Meta
className="meta"
title={props.beer?.name}
description={props.beer?.tagline}
/>
</Card>
);

I want to click anywhere on the box to navigate me to the post detail page except the buttons. It's buttons should it's own job

import {
Box,
Flex,
Text,
Input,
Image,
useColorModeValue,
useClipboard,
Divider,
IconButton,
HStack,
Menu,
MenuButton,
MenuList,
Portal,
MenuItem,
useToast,
useOutsideClick,
useDisclosure,
} from "#chakra-ui/react";
import {
BsThreeDots,
BsDot,
BsBookmark,
BsFlag,
BsCheckCircle,
} from "react-icons/bs";
import { BsHeart } from "react-icons/bs";
import { AiFillHeart, AiFillMessage } from "react-icons/ai";
import { FaShareSquare } from "react-icons/fa";
import parse from "html-react-parser";
import copyLink from "#/images/copy-link.svg";
import { axiosInstance } from "#/axiosConfig";
import { COLORS } from "../../constants/COLORS";
import dayjs from "dayjs";
import relativeTime from "dayjs/plugin/relativeTime";
import { useDispatch, useSelector } from "react-redux";
import { Link, useNavigate } from "react-router-dom";
import { addNotice, deleteMyPostSlice } from "../../redux/slices/userSlice";
import { FiEdit } from "react-icons/fi";
import { HiOutlineTrash } from "react-icons/hi";
import {
addComment,
deletePost,
publishPost,
unPublishPost,
} from "../../redux/asyncActions/postAction";
import CustomImage from "../small/CustomImage";
import {
deletePostSlice,
removeBookmarkSlice,
} from "../../redux/slices/postSlice";
import {
EmailShareButton,
FacebookShareButton,
TwitterShareButton,
LinkedinShareButton,
FacebookIcon,
TwitterIcon,
LinkedinIcon,
EmailIcon,
} from "react-share";
import AddPicker from "../small/AddPicker";
import PostTag from "./PostTag";
import LikedPeople from "../small/LikedPeopleModal";
import { useRef } from "react";
import ReportModal from "../common/ReportModal";
dayjs.extend(relativeTime);
var domain = window.location.host;
const NewsFeedPost = ({ data }) => {
const [liked, setLiked] = useState(data?.has_liked);
const [hasFav, setHasFav] = useState(data?.has_favorited);
const [likedCount, setLikedCount] = useState(data?.likers_count);
const [commentInput, setCommentInput] = useState("");
const { isOpen, onOpen, onClose } = useDisclosure();
const userId = useSelector((state) => state.userReducer?.userInfo?.id);
const { hasCopied, onCopy } = useClipboard(
`${domain}/post-detail/${data?.id}`
);
const toast = useToast();
const bg = useColorModeValue("white", COLORS.darkGray);
const borderColor = useColorModeValue(
COLORS.lightGrayBorder,
COLORS.darkGrayBorder
);
const navigate = useNavigate();
const ref = useRef();
const [isModalOpen, setIsModalOpen] = useState(false);
useOutsideClick({
ref: ref,
handler: () => setIsModalOpen(false),
});
const dispatch = useDispatch();
const likeThisPost = async (post_id) => {
try {
const r = await axiosInstance.post(`post/like/${post_id}`);
setLikedCount(r.data.likers_count);
setLiked((prev) => !prev);
} catch (err) {}
};
const bookmarkThisPost = async (post_id) => {
try {
const r = await axiosInstance.post(`post/favorite/${post_id}`);
setHasFav(r.data.favorited);
if (r.data.favorited) {
dispatch(addNotice("This post has been bookmarked"));
} else {
dispatch(addNotice("Bookmark has been removed"));
}
dispatch(removeBookmarkSlice(post_id));
} catch (err) {}
};
const deleteThisPost = (id) => {
dispatch(deletePost(id));
dispatch(deleteMyPostSlice(id));
};
const addMyComment = (e, id) => {
e.preventDefault();
let data = {
post_id: id,
content: commentInput,
};
dispatch(addComment(data));
navigate(`/post-detail/${id}`, { replace: true });
};
const unPublishPosts = (id) => {
dispatch(unPublishPost(id));
dispatch(deletePostSlice(id));
};
const publishPosts = (id) => {
dispatch(publishPost(id));
dispatch(deleteMyPostSlice(id));
};
return (
<Box
bg={bg}
mt="1.5rem"
p="1.5rem"
pt="0.8rem"
borderWidth={1}
borderColor={borderColor}
style={{ borderRadius: "10px" }}
onClick={() => navigate(`/post-detail/${data?.id}`)}
>
<Flex mb="1.5rem" align="center" direction="row" justify="space-between">
<Link to={`/post-detail/${data?.id}`}>
<Text fontWeight="400">{data?.title}</Text>
</Link>
<Menu>
<MenuButton>
<BsThreeDots />
</MenuButton>
<Portal>
<MenuList w="100px" p="3" bg={bg}>
{data?.user.id === userId ? (
<Flex direction={"column"} ml="1rem">
<Link to={`/post-edit/${data?.id}`}>
<Flex className="menuitems">
<FiEdit />
<Text ml="4" fontSize="0.8rem">
Edit
</Text>
</Flex>
</Link>
<Flex
className="menuitems"
onClick={() => deleteThisPost(data?.id)}
>
<HiOutlineTrash />
<Text ml="4" fontSize="0.8rem">
Delete
</Text>
</Flex>
{!data.is_published ? (
<Flex
className="menuitems"
onClick={() => publishPosts(data?.id)}
>
<BsCheckCircle />
<Text ml="4" fontSize="0.8rem">
Publish
</Text>
</Flex>
) : (
<Flex
className="menuitems"
onClick={() => unPublishPosts(data?.id)}
>
<FiEdit />
<Text ml="4" fontSize="0.8rem">
Unpublish
</Text>
</Flex>
)}
<Flex
className="menuitems"
onClick={() => bookmarkThisPost(data?.id)}
>
<BsBookmark color={hasFav ? "lightgreen" : ""} />
<Text ml="4" fontSize="0.8rem">
{hasFav ? "Remove Bookmark" : "Bookmark"}
</Text>
</Flex>
</Flex>
) : (
<Flex direction={"column"} ml="1rem">
<Flex
className="menuitems"
onClick={() => bookmarkThisPost(data?.id)}
>
<BsBookmark color={hasFav ? "lightgreen" : ""} />
<Text ml="4" fontSize="0.8rem">
{hasFav ? "Remove Bookmark" : " Bookmark"}
</Text>
</Flex>
<Flex className="menuitems" onClick={onOpen}>
<BsFlag />
<Text ml="4" fontSize="0.8rem">
Report
</Text>
<ReportModal
modalIsOpen={isOpen}
closeModal={onClose}
type="post"
id={data?.id}
/>
</Flex>
</Flex>
)}
</MenuList>
</Portal>
</Menu>
</Flex>
<Flex direction="row" align="center" justify="space-between">
<Box>
<Flex direction="row" align="center">
<Link to={`/user-profile/${data?.user?.id}`}>
<CustomImage
size="50px"
char={data.user?.firstname.charAt(0)}
imageUrl={data?.user?.photo}
alt={`${data.user?.firstname}'s Avatar`}
role={data?.user?.role}
/>
</Link>
<Flex ml="1rem" direction="column">
<Link to={`/user-profile/${data?.user?.id}`}>
<Text
fontSize={["12px", "13px", "13px", "13px"]}
mb="2px"
fontWeight="500"
>
{data?.user?.firstname} {data?.user?.lastname}
</Text>
</Link>
<Flex direction="row" align="center">
<Text
style={{ color: "#ABAAAF" }}
fontSize={["9px", "9px", "9px", "12px"]}
>
{dayjs(data.created_at).fromNow()}
</Text>
<BsDot
color="#ABAAAF"
fontSize={"20px"}
// fontSize={["14px","14px","15px","24px"]}
ml="4px"
/>
<Flex fontSize="10px" ml="4px">
in{" "}
<Text
ml="1"
cursor="pointer"
color="#FF8053"
onClick={() =>
navigate(`/?category_id=${data?.category?.id}`)
}
>
{data?.category?.name}
</Text>
</Flex>
</Flex>
</Flex>
</Flex>
</Box>
{data.tags && <PostTag tags={data?.tags} />}
</Flex>
<Box className="parseContent" mt="1.5rem" fontSize="12px">
<Link to={`/post-detail/${data?.id}`}>{parse(data.content_html)}</Link>
</Box>
<Divider mt="1rem" mb="0.5rem" />
<Flex
direction="row"
justify={{ base: "start", sm: "space-between" }}
mt="1rem"
align="center"
>
<Box w={{ base: "50%", sm: "50%", md: "70%", lg: "70%" }}>
<Box pos="relative">
<form
onSubmit={(e) => addMyComment(e, data?.id)}
style={{ position: "relative" }}
>
<Input
value={commentInput}
onChange={(e) => setCommentInput(e.target.value)}
fontSize={["9px", "10px", "12px", "12px"]}
placeholder="Add Response..."
// zIndex={0}
/>
<AddPicker setInput={setCommentInput} />
</form>
</Box>
</Box>
<Box width={{ base: "45%", sm: "45%", lg: "40%" }} pl="1.5rem">
<Flex direction="row" justify="space-around" position="relative">
<Flex direction="row" align="center">
<IconButton
onClick={() => likeThisPost(data.id)}
_hover={{ background: "transparent" }}
_active={{ background: "transparent" }}
_focus={{ boxShadow: "none" }}
bg="transparent"
color="#C5D0E6"
children={
liked ? (
<AiFillHeart fontSize={"1.7rem"} color={COLORS.hasLiked} />
) : (
<BsHeart fontSize={"1.4rem"} />
)
}
/>
<Text
color="#ABAAAF"
fontSize="14px"
onClick={() => setIsModalOpen(true)}
cursor="pointer"
>
{likedCount}
</Text>
{isModalOpen && (
<Box ref={ref}>
<LikedPeople />
</Box>
)}
</Flex>
<Link to={`/post-detail/${data?.id}`}>
<DataIconCount icon="AiFillMessage" count={data.comments_count} />
</Link>
<Menu>
<MenuButton
bg="transparent"
color="#C5D0E6"
_hover={{ background: "transparent", color: "#7B6CB4" }}
_active={{ background: "transparent" }}
_focus={{ boxShadow: "none" }}
className="newsfeed-iconbtn"
as={IconButton}
aria-label="Options"
icon={<FaShareSquare fontSize={"1.5rem"} />}
/>
<MenuList bg={bg}>
<MenuItem fontSize="12px">
<HStack align="center" gap="4px">
<FacebookShareButton
url={`${domain}/post-detail/${data?.id}`}
>
<Flex>
<FacebookIcon size={22} />
<Text ml="3">Facebook</Text>{" "}
</Flex>
</FacebookShareButton>
</HStack>
</MenuItem>
<MenuItem fontSize="12px">
<TwitterShareButton url={`${domain}/post-detail/${data?.id}`}>
<Flex>
<TwitterIcon size={22} />
<Text ml="3">Twitter</Text>{" "}
</Flex>
</TwitterShareButton>
</MenuItem>
<MenuItem fontSize="12px">
<LinkedinShareButton
url={`${domain}/post-detail/${data?.id}`}
>
<Flex>
<LinkedinIcon size={22} />
<Text ml="3">LinkedIn</Text>{" "}
</Flex>
</LinkedinShareButton>
</MenuItem>
<MenuItem fontSize="12px">
<EmailShareButton url={`${domain}/post-detail/${data?.id}`}>
<Flex>
<EmailIcon size={22} />
<Text ml="3">Mail</Text>
</Flex>
</EmailShareButton>
</MenuItem>
<MenuItem fontSize="12px">
<HStack
onClick={() => {
onCopy();
toast({
description: "Copied Post Link",
status: "success",
position: "top-right",
});
}}
align="center"
gap="4px"
>
<Image src={copyLink} />
<Text>Copy Link</Text>
</HStack>
</MenuItem>
</MenuList>
</Menu>
</Flex>
</Box>
</Flex>
</Box>
);
};
I
I have a post where there are lots of button. Each button has it's own task. Whenever I click on any white space or anywhere except this buttons, I should get navigated to post details page. So I have assigned navigate function on the onclick of the parent container that is "Box". The issue is that since all children are wrapped in box so clicking on those buttons also navigate . I want to navigate only on white spaces. I wrote a clumsy way of using e.stopPropagation() so buttons click prevent navigate() but still few buttons are navigating. Is there any way of navigating only when anywhere except buttons?
In the click event listener, check if the event current target is not a button.
if(!evt.currentTarget.matches('button'))

I can not display data from django rest framework with axios

I am still new.
I am making my portfolio.But I got problem.
I am trying to get data from django rest framework with axios. It says I got no error.
I want to display the data in cards components.
But still it does not show data in the browser.
How can I solve this problem?
Thank you in advance.
//App.tsx
const App: React.FC = () => {
const [loading, setLoading] = useState(false);
const [results, setResults] = useState<EventProps[]>([]);
const url = "http://127.0.0.1:8000/events/lists/";
useEffect(() => {
const getEventsData = async () => {
try {
const res = await axios.get<EventProps[]>(url).then((res) => {
setResults(res.data);
setLoading(true);
// console.log(res.data.results.event_id);
console.log(res);
console.log(res.data);
});
} catch (err) {
console.log(err);
}
};
getEventsData();
}, []);
return (
<>
<div className="wholeheader">
<MantineProvider
inherit
theme={{ defaultGradient: { from: "blue", to: "teal", deg: 20 } }}
>
<Group position="apart" grow>
<Center
sx={(theme) => ({
height: 170,
backgroundImage: theme.fn.gradient(),
color: theme.white,
})}
>
<Logo />
<div className="header">
<HeaderTabsColored {...HeaderProps} />
<LoginAndRegiInHeader />
</div>
<div className="searchbar">
<SearchBar />
</div>
</Center>
</Group>
</MantineProvider>
</div>
{loading ? (
<Fragment>loading..</Fragment>
) : (
Object.values(results).map((result: EventProps) => (
<EventsCard
key={result.event_id}
event_id={result.event_id}
title={result.title}
description={result.description}
dateTime={result.dateTime}
capacity={result.capacity}
EventImage1={result.EventImage1}
EventImage2={result.EventImage2}
EventImage3={result.EventImage3}
location={result.location}
host={result.host}
/>
))
)}
<br />
<br />
<Page />
</>
);
};
export default App;
//Events.tsx
[data in the browser][1]
import { EventProps } from "../types/EventsProps";
import { Grid } from "#mantine/core";
import axios from "axios";
import { ThemeContext } from "#emotion/react";
import eventImage from "../Images/Events/eventImage.jpg";
const useStyles = createStyles((theme) => ({
card: {
backgroundColor:
theme.colorScheme === "dark" ? theme.colors.dark[7] : theme.white,
},
section: {
borderBottom: `1px solid ${
theme.colorScheme === "dark" ? theme.colors.dark[4] : theme.colors.gray[3]
}`,
paddingLeft: theme.spacing.md,
paddingRight: theme.spacing.md,
paddingBottom: theme.spacing.md,
},
like: {
color: theme.colors.red[6],
},
label: {
textTransform: "uppercase",
fontSize: theme.fontSizes.xs,
fontWeight: 700,
},
}));
// {EventImage1, EventImage2, EventImage3, event_id, location, description, capacity, title, host,dateTime}:
const EventsCard: React.FC<EventProps> = (props) => {
const { classes, theme } = useStyles();
const [opened, setOpened] = useState(false);
return (
<Grid>
<Grid.Col span={4} key={props.event_id}>
<Card withBorder radius="md" p="md" className={classes.card}>
<Card.Section>
<Image
className="image"
src={props.EventImage1}
alt={props.title}
height={300}
width={342}
/>
<Image
className="image"
src={props.EventImage2}
alt={props.title}
height={300}
width={342}
/>
<Image
className="image"
src={props.EventImage3}
alt={props.title}
height={300}
width={342}
/>
</Card.Section>
<Card.Section className={classes.section} mt="md">
<Group position="apart">
<Text size="lg" weight={800}>
{props.title}
<br />
{props.dateTime}
</Text>
<Badge size="sm">{props.location}</Badge>
</Group>
<Text size="lg" weight={500}>
定員:{props.capacity}名
</Text>
<Text size="sm" mt="xs">
{props.description}
</Text>
</Card.Section>
<Card.Section className={classes.section}>
<Text mt="md" className={classes.label} color="dimmed">
host
</Text>
<Text size="sm">{props.host}</Text>
</Card.Section>
</Card>
</Grid.Col>
</Grid>
);
};
export default EventsCard;

Why my props are undefined when sending to components?

I have a table in my project and I have an edit / view / add page that I can access from this table. My goal is to send the clicked data to the other component without any problem, but no matter how hard I try, I get an undefined error and the project is broken. I would be glad if you could help.
I am sharing my codes from parent to child component
Table page.
import React, { useState, useEffect, useCallback, useMemo } from "react";
import ManagementTable from '../components/ManagementTable'
import {
getApps,
updateStopRisk,
countLiveCountry,
updateAppShow,
deleteApp,
} from "../api/apiCalls";
import VisibilityIcon from "#material-ui/icons/Visibility";
import DeleteIcon from "#material-ui/icons/Delete";
import EditIcon from "#material-ui/icons/Edit";
import Switch from "#material-ui/core/Switch";
import DeleteModal from "../components/DeleteModal";
import { Link } from "react-router-dom";
const Management = () => {
const [apps, setApps] = useState([]);
const [modalVisible, setModalVisible] = useState(false);
const [currentApp, setCurrentApp] = useState("");
const [appID, setAppID] = useState(0);
const fetchData = useCallback(async () => {
const { data: appsResponse } = await getApps();
const countLiveCountries = await fetchLiveCountriesForApps(appsResponse);
setApps(
appsResponse.map((app, idx) => ({
...app,
countLiveCountry: countLiveCountries[idx],
}))
);
}, []);
useEffect(() => {
fetchData();
}, [fetchData]);
const fetchLiveCountriesForApps = async (appwLive) => {
const countLiveCountries = await Promise.all(
appwLive.map((app) => countLiveCountry(app.appID))
);
return countLiveCountries.map(({ data: liveCountries }) => liveCountries);
};
const removeApp = async () => {
await deleteApp(appID);
setModalVisible(false);
fetchData();
};
const onClickCancel = () => {
setModalVisible(false);
};
const columns = useMemo(() => [
{
Header: "Application Name",
accessor: "app_name",
},
{
Header: "Business Area",
accessor: "businessarea.businessarea_name",
},
{
Header: "Live Plants",
accessor: "countLiveCountry",
},
{
Header: "Line Stop Risk",
accessor: "app_stoprisk",
Cell: ({ row: { original } }) => {
const changeCheck = async (id) => {
await updateStopRisk(id);
fetchData();
};
return (
<input
checked={original.app_stoprisk}
onClick={() => {
changeCheck(original.appID);
}}
id="appStopRisk"
type="checkbox"
style={{ width: 18, height: 18, marginTop: 5 }}
/>
)
},
sortType: (a, b, id) => {
if (a.original[id] > b.original[id]) return -1;
if (b.original[id] > a.original[id]) return 1;
},
},
{
Header: "Actions",
Cell: ({ row: { original } }) => {
const changeTrack = async (id) => {
await updateAppShow(id);
fetchData();
};
return (
<>
<Link
className="btn btn-manage-link btn-sm col-2"
to={{
pathname: `/management/${original.app_name}`,
mode: "view",
id: original.appID
}}
>
<VisibilityIcon></VisibilityIcon>
</Link>
<Link
to={{
pathname: `/management/${original.app_name}`,
mode: "edit",
id: original.appID
}}
className="btn btn-manage-link btn-sm col-2"
>
<EditIcon></EditIcon>
</Link>
<button
onClick={() => {
setModalVisible(true);
setCurrentApp(original.app_name);
setAppID(original.appID);
}}
className="btn btn-manage-link btn-sm col-3"
>
<DeleteIcon></DeleteIcon>
</button>
<Switch
onClick={() => changeTrack(original.appID)}
checked={original.app_show}
className="col-3"
></Switch>
</>
)
},
},
],
[fetchData]
);
return (
<div className="container">
<h2 style={{ float: "left", font: "bold" }}>Management</h2>
<div style={{ float: "right" }}>
<Link className="btn btn-danger btn-sm" to={{ pathname: `/management/add`, mode: "add" }}>
Add New App
</Link>
<Link className="btn btn-danger btn-sm ml-3" exact to="/management/plants">
Plant Management
</Link>
</div>
<ManagementTable columns={columns} data={apps} />
<DeleteModal
message={<strong>{currentApp}</strong>}
variety="app"
onClickCancel={onClickCancel}
onClickOk={removeApp}
visible={modalVisible}
/>
</div>
);
};
export default Management;
The page where I transfer the props.
import React, { useState, useEffect } from "react";
import Accordion from "../components/Accordion";
import Details from '../components/Details'
import {
getByIdApps,
} from "../api/apiCalls";
const ApplicationManagement = (props) => {
const [appById, setAppById] = useState([]);
const { id } = props.location;
const [selectOption, setSelectOption] = useState('add')
useEffect(() => {
getData();
getMode();
}, [])
const getData = async () => {
console.log(props.location.id)
if (props.location.id) {
await getByIdApps(props.location.id).then((response) => setAppById(response.data))
console.log(appById)
console.log(props)
}
else {
setSelectOption('add')
}
}
const getMode = () => props.location.mode ? setSelectOption(props.location.mode) : setSelectOption('add')
const handleOptionChange = (event) => {
console.log(event.target.value)
setSelectOption(event.target.value)
}
return (
<>
<div style={{ margin: 20 }}>
<h1>
{appById.app_shortcode} - {appById.app_fullname}
</h1>
<div className="float-right mb-auto">
<label><input type="radio" value="view" checked={selectOption === 'view'} onChange={handleOptionChange} />View</label>
<label> <input type="radio" value="add" checked={selectOption === 'add'} onChange={handleOptionChange} />Add</label>
<label> <input type="radio" value="edit" checked={selectOption === 'edit'} onChange={handleOptionChange} />Edit</label>
</div>
<br></br>
<div style={{ marginLeft: 50, marginRight: 50 }} >
<Accordion
title={
<div style={{ width: 1350 }}>
<h3>Details</h3>
<hr style={{ backgroundColor: "#aaa" }}></hr>
</div>
}
content={
<Details appID={id} data = {appById}></Details>
}
/>
<Accordion title={
<div style={{ width: 1350 }}>
<h3>Links</h3>
<hr style={{ backgroundColor: "#aaa" }}></hr>
</div>
}></Accordion>
<Accordion title={
<div style={{ width: 1350 }}>
<h3>Factory Management</h3>
<hr style={{ backgroundColor: "#aaa" }}></hr>
</div>
}></Accordion>
<Accordion title={
<div style={{ width: 1350 }}>
<h3>Issues Management</h3>
<hr style={{ backgroundColor: "#aaa" }}></hr>
</div>
}></Accordion>
<Accordion title={
<div style={{ width: 1350 }}>
<h3>Middleware Management</h3>
<hr style={{ backgroundColor: "#aaa" }}></hr>
</div>
}></Accordion>
</div>)
{selectOption === 'add' ? (
<div>
Add Mode
</div>
) : selectOption === 'view' ? (<div>View Mode</div>) : (<div>eidt</div>)}
</div>
</>
);
};
export default ApplicationManagement;
and the section where the details are kept on the ApplicationManagement page (My code is quite long, I just share the problem part.)
import React, { useState, useEffect } from 'react'
import axios from "axios";
import {
getResponsibleTeams,
getBusinessAreas
} from '../api/apiCalls'
const Details = (props) => {
const [rTeams, setrTeams] = useState([]);
const [bAreas, setbAreas] = useState([]);
const { data } = props;
useEffect(() => {
async function fetchData() {
const getrTeams = await getResponsibleTeams();
const getbAreas = await getBusinessAreas();
axios.all([getrTeams, getbAreas]).then(
axios.spread((...allData) => {
const allrTeams = allData[0].data;
const allbAreas = allData[1].data;
setrTeams(allrTeams);
setbAreas(allbAreas);
})
);
}
fetchData();
}, []);
return (
<div>
<div
style={{
float: "left",
width: 1350,
height: 340,
}}
>
<div className="form-group">
<label style={{ float: "left" }} htmlFor="appFullName">
Frontend:{" "}
</label>
<input
id="appFullName"
type="text"
class="form-control"
placeholder="dsfdsdsf"
value={data.frontend.frontend_name} // error here
//onChange={handleInputChange}
name="appShortCode"
style={{ width: 400, marginLeft: 150 }}
/>
</div>
</div>
</div>
)
}
export default Details;
Later I realized that using asynchronous functions caused some problems. I came up with a solution to this and the problem was solved.
Error Code Here :
<Accordion
title={
<div style={{ width: 1350 }}>
<h3>Details</h3>
<hr style={{ backgroundColor: "#aaa" }}></hr>
</div>
}
content={
<Details appID={id} data = {appById}></Details>
}
/>
and the solution to the problem
{appById &&
<Accordion
title={
<div style={{ width: 1350 }}>
<h3>Details</h3>
<hr style={{ backgroundColor: "#aaa" }}></hr>
</div>
}
content={
<Details appID={id} data = {appById}></Details>
}
/>}

Type Error with const in react in products page

When I compile the code it is throwing an error below is the error
compiled inside VS Code, using React
Here below is the code in my ProductPage.js
import React, { useEffect, useContext, useState } from "react";
import { useParams } from "react-router-dom";
import { ShopContext } from "../../context/shopContext";
import { Text, Div, Button, Row, Col, Container, Image, ThemeProvider } from "atomize";
import { Link } from "react-router-dom";
import { ReactComponent as HeartIcon } from "../../icons/heart.svg";
const theme = {
grid: {
colCount: 8,
gutterWidth: 0
}
};
const ProductPage = () => {
let { id } = useParams();
const { fetchProductWithId, addItemToCheckout, product, client } = useContext(
ShopContext
);
const [sizeIndex, setSizeIndex] = useState('');
const [colorIndex, setColorIndex] = useState('');
const [favoriteText, setFavoriteText] = useState("Add to Favorite");
useEffect(() => {
fetchProductWithId(id);
return () => {};
}, [fetchProductWithId, id]);
if (!product.title) return <div>loading</div>;
const selectedVariant = client.product.helpers.variantForOptions(product, {
Size: sizeIndex || product.options[0].values[0].value,
Color: colorIndex || product.options[1].values[0].value
});
return (
<Container>
<ThemeProvider theme={theme}>
<Row bg="black" rounded="lg" d="flex"
m="6rem">
<Col size={{ xs: 8, lg: 5 }}>
<Image src={product.images[0].src} w="20rem" p="2rem"/>
</Col>
<Col size={{ xs: 8, lg: 3 }} align="space-around" >
<Text tag="h1" textColor="white" textWeight="200" m={{ y: "2rem" }} >
{product.title}
</Text>
<Text tag="h3" textColor="white" m={{ y: "2rem" }} textWeight="200">
€ {product.variants[0].price}
</Text>
<select value={sizeIndex} onChange={e => setSizeIndex(e.target.value)} >
{product.options[0].values.map((item, index) => (
<option value={item.value}>{item.value}</option>
))
}
</select>
<select value={colorIndex} onChange={e => setColorIndex(e.target.value)} >
{product.options[1].values.map((item, index) => (
<option value={item.value}>{item.value}</option>
))
}
</select>
<Button
rounded="lg"
shadow="3"
bg="black500"
m={{ y: "2rem" }}
onClick={() => addItemToCheckout(product.variants[0].id, 1)}
>
Add to Cart
</Button>
<Button rounded="lg"
shadow="3"
bg="black500"
m={{ y: "2rem" }}
onClick={() => {
// console.log(product);
let favorites = JSON.parse(localStorage.getItem('favorites') || "[]");
const productExists = favorites.find(favorite => favorite.id === product.id);
if(productExists) {
favorites = favorites.filter(favorite => favorite.id !== product.id);
setFavoriteText("Add to Favorite")
localStorage.setItem('favorites', JSON.stringify(favorites));
} else {
favorites = [...favorites, product];
setFavoriteText("Remove from Favorite");
localStorage.setItem('favorites', JSON.stringify(favorites));
}
}}>
{/* <HeartIcon title="Add to Favourites" style={{height: '25px', width: '25px', backgroundColor: "#fff", color: "red" }} /> */}
{favoriteText}
</Button>
</Col>
</Row>
</ThemeProvider>
</Container>
);
};
export default ProductPage;
if (!product.title) return <div>loading</div>;
const selectedVariant = client.product.helpers.variantForOptions(product, {
Size: sizeIndex || product.options[0].values[0].value,
Color: colorIndex || product.options[1].values[0].value
});
Your problem is in this part. Since you only return a "loader" if the title parameter is undefined and not if the entire product object is undefined. Your error clearly states that it is trying to access a parameter on an undefined object, in this case it refers to product being undefined.
The solution is to either return the "loader" if product is undefined or make sure that product is initialized with some default values, so that its never undefined.

Resources