So basically every time a navigate to a different page in this case from home page to /blog using next-link I get Unhandled Runtime Error
TypeError: destroy is not a function
but when I refresh the page the page loads correctly or if I type in the URL manually in the browser for instance localhost:3000/blog
here is a screenshots of the error
and here is the code for the blog page
///blog page
export default function Blog(props) {
const { posts, tags } = props;
function switchMode() {
props.setMode(props.mode === 'light' ? 'dark' : 'light');
}
return (
<>
<Head>
<title>Blog</title>
<link rel="icon" href="/favicon.ico" />
<meta name="description" content="Yushae Raza's personal blog" />
</Head>
<main style={{ paddingTop: "5em" }}>
<Container>
<Typography variant="h1" align="center" >
Blog
</Typography>
<Divider />
<br></br>
<Grid container spacing={2}>
<Grid item xs={12} md={8}>
{posts.map((post, idx) => (<>
<Post
title={post.title}
publishedAt={post.published_at}
author={post.authors[0].name}
imageUrl={post.feature_image}
description={post.excerpt}
category={post.tags[0].name}
slug={post.slug} /><br></br>
</>)
)}
</Grid>
<Grid item xs={12} md={4}>
<Sidebar tags={tags} />
</Grid>
</Grid>
</Container>
</main>
</>
)
}
export async function getStaticProps() {
// get posts from our api
const { posts } = await api.getPosts(0);
const { tags } = await api.getTags();
// console.log(posts)
return {
props: { posts, tags },
revalidate: 10
};
}
//navbar
const pages = [
{ name: 'Blog', link: '/blog' },
]
{pages.map((page, idx) => (
<MenuItem key={idx} onClick={handleCloseNavMenu}
sx={{ flexGrow: 1 }}>
<Link href={page.link}>
{page.name}
</Link>
</MenuItem>
))}
//api.js
const backendUrl = 'https://yr-blog.herokuapp.com/'
export const getPosts = (page) => {
console.log(process.env.API_KEY)
return fetch(
`${backendUrl}ghost/api/v4/content/posts/?key=${process.env.API_KEY}&order=published_at%20desc&include=authors,tags&page=${page}&fields=title,slug,feature_image,published_at,excerpt&formats=plaintext`
).then((res) => res.json())
}
export const getSlugs = (page) => {
console.log(process.env.API_KEY)
return fetch(
`${backendUrl}ghost/api/v4/content/posts/?key=${process.env.API_KEY}&order=published_at%20desc&fields=slug`
).then((res) => res.json())
}
export const getTags = () => {
return fetch(
`${backendUrl}ghost/api/v4/content/tags/?key=${process.env.API_KEY}&fields=name,slug`
).then((res) => res.json())
}
export const getTagsSlugs = () => {
return fetch(
`${backendUrl}ghost/api/v4/content/tags/?key=${process.env.API_KEY}&fields=slug`
).then((res) => res.json())
}
export const getTagName = (slug) => {
return fetch(`${backendUrl}ghost/api/v4/content/tags/?key=${process.env.API_KEY}&filter=slug:${slug}&fields=name`).then((res) => res.json());
}
export const getPost = (slug) => {
return fetch(`${backendUrl}ghost/api/v4/content/posts/?key=${process.env.API_KEY}&filter=slug:${slug}&order=published_at%20desc&include=authors,tags&fields=html,title,slug,feature_image,published_at`).then((res) => res.json())
}
export const getPostsByTag = (tag, page) => {
return fetch(`${backendUrl}ghost/api/v4/content/posts/?key=${process.env.API_KEY}&filter=tags:${tag}&order=published_at%20desc&include=authors,tags&page=${page}&fields=title,slug,feature_image,published_at,excerpt&formats=plaintext`).then((res) => res.json())
}
//home page
export default function Home(props) {
useEffect(() => {
TagCloud(".test", [
'JavaScript', 'CSS', 'HTML',
'C', 'C++', 'React',
'Python', 'Java', 'git',
'django', 'Node.js', 'Express.js',
'MySQL', 'jQuery',
'Bootstrap', 'Material-UI',
'Next.js', 'React-Native',
'Firebase', 'Apache',
'MongoDB', 'SQL',
'TypeScript', 'Git',
], {
radius: screen.width > 500 ? 300 : 100,
// slow, normal, fast
maxSpeed: 'fast',
initSpeed: 'fast',
// 0 = top
// 90 = left
// 135 = right-bottom
direction: 135,
keep: false,
});
return () => {
let tagClouds = document.getElementsByClassName('tagcloud');
for (let i = 0; i < tagClouds.length; i++) {
tagClouds[0].remove();
}
};
}, []);
Update 1 I narrowed down the issue to the animateletters component which detailed below
const AnimatedLetters = (props) => {
const [letterClass, setLetterClass] = useState('letter-intro');
useEffect(() => {
return setTimeout(() => {
setLetterClass('letter-hover');
}, 4000)
}, []);
const letters = props.title.split("");
const length = letters.length;
return (
<StyledSpan length={length} useDefaultColor={props.useDefaultColor}>
{letters ? letters.map((char, index) => {
return (
<span className={`letter ${letterClass} _${index}`} key={index}>{char}</span>
);
}) : null}
</StyledSpan>
)
}
export default AnimatedLetters;
Related
The main page brings data.
When page url changes, useInfiniteQuery can't get JSON data.
What I suspect is this
On the network in the browser console it shows:'You need to enable JavaScript to run this app.'
this is my code
File Structure
fublic/
data/
youtube.json
...
src/
conponent/
nav/
nav.jsx
hooks/
useList.jsx
routes/
mainContent.jsx
router configuration
const router = createBrowserRouter([
{ path: '/', element: <Nav />,
children: [
{ index: true, element: <MainContent />},
{ path: 'videos/:searchId', element: <MainContent />},
{ path: '/videos/detail/:videoId', element: <VideoDetail />}
]
}
])
Nav.jsx code
export default function Nav() {
const [list, setList] = useState(
{ listUrl: 'data/youtube&pageToken=', key: 'mainList'})
const handleUrl = (url, key) => {
setList({listUrl: url, key})}
return (
<>
<header className='main_heder'>
<h1>logo</h1>
<NavSearch
handleUrl={handleUrl}
/>
</header>
<Outlet context={list} />
</>
);
}
MainContent.jsx code
export default function MainContent() {
const list = useOutletContext()
const [data, status, hasNextPage, fetchNextPage, nowtime] = useList(list)
const { ref, inView } = useInView({threshold: 0});
const onFetchNextPage = () => {
if (hasNextPage && inView) {
fetchNextPage();}}
const getFilteredLists = (list) => {
return list.pages.map((group) => group.items.filter((item) => !item.id.channelId)
)}
useEffect(onFetchNextPage,[inView])
return (
<>
<InView
as='div'
onChange={onFetchNextPage}
>
<main className='main_contents'>
{status === 'loading' ? <p>Loading...</p> :
getFilteredLists(data).map((group) => (
group.map((movie) => (
<MainMovieList
key={movie.id}
movie={movie}
time={nowtime}
/>
))))}
<div ref={ref}></div>
<>
</>
</main>
</InView>
</>
);
}
useList.jsx code
export default function useList( {listUrl}) {
const fetchProducts = async ({ pageParam = '' }) => {
const data = await (
await fetch(`${listUrl + pageParam}.json`)
).json();
return data;
};
const {
data,
error,
fetchNextPage,
hasNextPage,
status,
} = useInfiniteQuery([listUrl,state], fetchProducts, {
getNextPageParam: (lastPage) => lastPage.nextPageToken,
refetchOnWindowFocus: false,
enabled:true
})
const nowtime = new Date().getTime()
return [data, status, hasNextPage, fetchNextPage, nowtime]
}
I want to receive json file when 'listUrl' value is changed in useList.jsx.
I don't know what to do, I've been trying to clear the state when closing for days and nothing happens. It even sets undefined, but the screen always starts with the loaded data and QUICKLY the data is rewritten.
I wanted that every time I opened the screen to read the lyrics of the songs, the data would start at zero. And when I exit or close this screen, I want the data to be reset, so that when I open it again, the screen starts loading from zero.
My Code:
const LycrsVagalume: React.FC = () => {
const [imageData, setImageData] = useState<iImageVagalumeApi>(
{} as iImageVagalumeApi,
);
const [musicVagalume, setMusicVagalume] = useState<iVagalumeApi>(
{} as iVagalumeApi,
);
const [loading, setLoading] = useState(true);
const [loadingImage, setLoadingImage] = useState(true);
const musicData = useRoute().params as MusicDTO;
const navigation = useNavigation();
const onShare = async () => {
try {
const response = await Share.share({
title: `Informações sobre a música: ${capitalizeText(
musicData?.music,
)}`,
message: `Informações da música:\n\nNúmero: ${
musicData?.code
}\nArtista: ${capitalizeText(
musicData?.artist,
)}\nMúsica: ${capitalizeText(musicData?.music)}`,
});
if (response.action === Share.sharedAction) {
return response;
}
} catch (error) {
captureError(error);
}
};
const vagalume = async (): Promise<void> => {
const apiKey = '850241bea0c9dd5850817b44e837ff94';
try {
const vagalumeApi = (await api.get(
`${api.defaults.baseURL}?art=${musicData?.artist}&mus=${musicData?.music}&apiKey=${apiKey}`,
)) as iVagalumeApi;
if (vagalumeApi.status == 200) {
setLoading(false);
setMusicVagalume(vagalumeApi);
}
} catch (error) {
captureError(error);
}
};
const handleLoadImage = async (): Promise<void> => {
try {
const apiKey = '850241bea0c9dd5850817b44e837ff94';
const limit = 2;
if (!!musicVagalume) {
const image = (await api.get(
`${imageApi.defaults.baseURL}?bandID=${musicVagalume?.data?.art?.id}&limit=${limit}&apiKey=${apiKey}`,
)) as iImageVagalumeApi;
if (image.status === 200) {
setLoadingImage(false);
setImageData(image);
}
}
} catch (error) {
captureError(error);
}
};
useFocusEffect(
useCallback(() => {
vagalume();
handleLoadImage();
}, [musicVagalume]),
);
useEffect(() => {
const unsubscribe = navigation.addListener('blur', () => {
setMusicVagalume(undefined);
setImageData(undefined);
});
return () => {
unsubscribe();
};
}, []);
return (
<Container>
<CloseIconButton onPress={() => navigation.goBack()}>
<CloseIcon name="close-circle" />
</CloseIconButton>
<Content>
<>
<Header>
<ThumbNail>
{imageData?.data?.images?.length > 0 &&
!loadingImage &&
musicVagalume?.data?.type !== 'notfound' ? (
<PhotoThumbnail
source={{uri: imageData?.data?.images[0]?.url}}
/>
) : (
<BandSvgContainer>
<RockBandSvg width={wp(65)} height={wp(45)} />
</BandSvgContainer>
)}
</ThumbNail>
<MusicContainer>
<MusicContent>
<ImageMusicContainer>
{imageData?.data?.images?.length > 0 &&
!loadingImage &&
musicVagalume?.data?.type !== 'notfound' ? (
<Photo
source={{
uri: !!imageData?.data?.images[1]?.url
? imageData?.data?.images[1]?.url
: imageData?.data?.images[0]?.url,
}}
/>
) : (
<SingerImage>
<SingerSvg width={wp(13)} height={wp(13)} />
</SingerImage>
)}
</ImageMusicContainer>
<MusicInformation>
<Artist numberOfLines={1} ellipsizeMode="tail">
{capitalizeText(musicData?.artist)}
</Artist>
<Music numberOfLines={1} ellipsizeMode="tail">
{capitalizeText(musicData?.music)}
</Music>
</MusicInformation>
</MusicContent>
<Hr />
<FooterMusicContent>
<Number>{musicData?.code}</Number>
<IconsMusicContent>
{/* <ButtonIconFavorites>
<IconFavorited
name={favorited ? 'cards-heart' : 'cards-heart-outline'}
favorited={favorited}
/>
</ButtonIconFavorites> */}
<ButtonShareFavorites onPress={onShare}>
<Icons name="share-variant-outline" />
</ButtonShareFavorites>
</IconsMusicContent>
</FooterMusicContent>
</MusicContainer>
</Header>
<Footer>
<VagalumeContent>
<VagalumeSvg width={wp(20)} height={wp(20)} />
</VagalumeContent>
{loading ? (
<LoadingContainer>
<Loading
source={loadingMusicLottie}
autoPlay
resizeMode="contain"
renderMode="HARDWARE"
/>
</LoadingContainer>
) : (
<LyrcsContent>
{musicVagalume?.data?.type == 'song_notfound' ||
musicVagalume?.data?.type == 'notfound' ? (
<>
<Lyrcs>
'Não encontamos nenhuma letra para essa música 😥'
</Lyrcs>
</>
) : (
<>
<Title>
{musicVagalume ? capitalizeText(musicData?.music) : ''}
</Title>
<Lyrcs>{musicVagalume?.data?.mus[0]?.text}</Lyrcs>
</>
)}
</LyrcsContent>
)}
</Footer>
</>
</Content>
</Container>
);
};
export default memo(LycrsVagalume);
Use case is to to open
http://localhost:3000/users/101
This is how I would like my page layout to be and Element pull in the second code snippet in [id].tsx
import CTASection from '../../components/samples/CTASection';
import { User } from "../../interfaces";
import { GetStaticProps, GetStaticPaths } from "next";
import Element from "pages/users/element";
const Element = ({ item, errors }: Props) => {
return (
<Box>
<Element />
<CTASection />
</Box>
)
}
export default Id;
export const getStaticPaths: GetStaticPaths = async () => {
// Get the paths we want to pre-render based on users
const paths = sampleUserData.map((user) => ({
params: { id: user.id.toString() },
}));
return { paths, fallback: false };
};
export const getStaticProps: GetStaticProps = async ({ params }) => {
try {
const id = params?.id;
const item = sampleUserData.find((data) => data.id === Number(id));
return { props: { item } };
} catch (error) {
return { props: { errors: 'ERROR Loading Data' } };
}
};
However it only renders the query parameters if I insert my element.tsx page in a non-modular fashion like this:
...
return (
<Box>
<Grid gap={2}>
<Heading as="h2" fontSize={{ base: "lg", sm: "3xl" }}>
Verifikation
</Heading>
<Box
backgroundColor={colorMode === "light" ? "gray.200" : "gray.500"}
padding={4}
borderRadius={4}
>
<Box fontSize={textSize} title={`${
item ? item.name : "User Detail"
}`}>
{item && <ListDetail item={item} />}
</Box>
</Box>
</Grid>
<CTASection />
</Box>
)
...
This is the ListDetail.tsx:
import * as React from "react";
import { User } from "../../interfaces";
type ListDetailProps = {
item: User;
};
const ListDetail = ({ item: user }: ListDetailProps) => (
<div>
<h1>User: {user.name}</h1>
<p>ID: {user.id}</p>
</div>
);
export default ListDetail;
you can use gerServerSideProps
export const getServerSideProps = async ({ req, res, query, params }) => {
// your code...
// you have access to req, res, query, params, headers, cookies, and many more.
return {
props: {}
}
}
I've two different prices,
when i check the checkbox for second price,
the state show and display the second price properly
but when i press the pay button of that product with second price, it will send the first price
instead of what I've checked which was second price.
so i want increment both prices separately when i checked the check box and
it sends the specific price to the payment process
import React, { useState, useEffect } from "react";
import {
getProducts,
getBraintreeClientToken,
processPayment,
createOrder
} from "./apiCore";
import { emptyCart } from "./cartHelpers";
import { isAuthenticated } from "../auth";
import { Link } from "react-router-dom";
import "braintree-web";
import DropIn from "braintree-web-drop-in-react";
import { makeStyles } from '#material-ui/core/styles';
import TextField from '#material-ui/core/TextField';
const useStyles = makeStyles((theme) => ({
root: {
'& > *': {
margin: theme.spacing(1),
width: '25ch',
},
},
}));
const Checkout = ({ products, setRun = f => f, run = undefined }) => {
const classes = useStyles();
const [data, setData] = useState({
loading: false,
success: false,
clientToken: null,
error: "",
instance: {},
address: "",
mobile:""
});
>>>>>> const [price, setPrice]= useState(() => () => getTotal())
>>>>>> const [isChecked, setIsChecked]= useState(false);
const userId = isAuthenticated() && isAuthenticated().user._id;
const token = isAuthenticated() && isAuthenticated().token;
const getToken = (userId, token) => {
getBraintreeClientToken(userId, token).then(data => {
if (data.error) {
setData({ ...data, error: data.error });
} else {
setData({ clientToken: data.clientToken });
}
});
};
useEffect(() => {
getToken(userId, token);
}, []);
const handleAddress = event => {
setData({ ...data, address: event.target.value });
};
const handleMobile = event => {
setData({ ...data, mobile: event.target.value });
};
>>>>>> const getTotal = () => {
>>>>>> return products.reduce((currentValue, nextValue) => {
>>>>>> return currentValue + nextValue.count * nextValue.price;
>>>>>>
>>>>>> }, 0);
>>>>>> };
>>>>>> const getTotal2 = () => {
>>>>>> return products.reduce((currentValue, nextValue) => {
>>>>>> return currentValue + nextValue.count * nextValue.price2;
>>>>>> }, 0);
>>>>>> };**
const showCheckout = () => {
return isAuthenticated() ? (
<div>{showDropIn()}</div>
) : (
<Link to="/signin">
<button className="btn btn-primary">Sign in to checkout</button>
</Link>
);
};
let deliveryAddress = data.address
let deliveryMobile = data.mobile
const buy = () => {
setData({ loading: true });
// send the nonce to your server
// nonce = data.instance.requestPaymentMethod()
let nonce;
let getNonce = data.instance
.requestPaymentMethod()
.then(data => {
// console.log(data);
nonce = data.nonce;
// once you have nonce (card type, card number) send nonce as 'paymentMethodNonce'
// and also total to be charged
// console.log(
// "send nonce and total to process: ",
// nonce,
// getTotal(products)
// );
>>>>>> **const paymentData = {
>>>>>> paymentMethodNonce: nonce,
>>>>>> amount: getTotal(products)
>>>>>> };**
processPayment(userId, token, paymentData)
.then(response => {
console.log(response);
// empty cart
// create order
const createOrderData = {
products: products,
transaction_id: response.transaction.id,
amount: response.transaction.amount,
address: deliveryAddress,
mobile: deliveryMobile
};
createOrder(userId, token, createOrderData)
.then(response => {
emptyCart(() => {
setRun(!run); // run useEffect in parent Cart
console.log(
"payment success and empty cart"
);
setData({
loading: false,
success: true
});
});
})
.catch(error => {
console.log(error);
setData({ loading: false });
});
})
.catch(error => {
console.log(error);
setData({ loading: false });
});
})
.catch(error => {
// console.log("dropin error: ", error);
setData({ ...data, error: error.message });
});
};
const showDropIn = () => (
<div onBlur={() => setData({ ...data, error: "" })}>
{data.clientToken !== null && products.length > 0 ? (
<div>
<div className="gorm-group mb-3">
<label className="text-muted">Delivery address:</label>
<textarea
onChange={handleAddress}
className="form-control"
value={data.address}
placeholder="Type your delivery address here..."
/>
</div>
<div className="gorm-group mb-3">
<label className="text-muted">mobile number:</label>
<form className={classes.root} noValidate autoComplete="off">
<TextField placeholder="mobile number" onChange={handleMobile} type="text" value={data.mobile} id="outlined-basic" label="mobile" variant="outlined" />
</form>
</div>
<DropIn
options={{
authorization: data.clientToken,
paypal: {
flow: "vault"
}
}}
onInstance={instance => (data.instance = instance)}
/>
<button onClick={buy} className="btn btn-success btn-block">
Pay
</button>
</div>
) : null}
</div>
);
const showError = error => (
<div
className="alert alert-danger"
style={{ display: error ? "" : "none" }}
>
{error}
</div>
);
const showSuccess = success => (
<div
className="alert alert-info"
style={{ display: success ? "" : "none" }}
>
Thanks! Your payment was successful!
</div>
);
const showLoading = loading =>
loading && <h2 className="text-danger">Loading...</h2>;
return (
<div>
>>>>>> **<form>
>>>>>> <h1>قیمت کل: {isChecked ? getTotal2() : getTotal()} </h1>
>>>>>> <label>نیم لیتر :</label>
>>>>> <input type="checkbox"
>>>>>> checked={isChecked}
>>>>>> onChange={(e)=>{setIsChecked(e.target.checked)}}/>
>>>>>> </form>**
{showLoading(data.loading)}
{showSuccess(data.success)}
{showError(data.error)}
{showCheckout()}
</div>
);
};
export default Checkout;
my card component
import React, { useState, version,useEffect } from 'react';
import { Link, Redirect } from 'react-router-dom';
import ShowImage from './ShowImage';
import moment from 'moment';
import { addItem, updateItem, removeItem } from './cartHelpers';
import logo from '../images/logo.svg'
//material ui
import Card from '#material-ui/core/Card';
import CardContent from '#material-ui/core/CardContent';
import { makeStyles } from '#material-ui/core/styles';
import Button from '#material-ui/core/Button';
import Grid from '#material-ui/core/Grid'
import { Typography } from '#material-ui/core';
import CardHeader from '#material-ui/core/CardHeader';
import CardMedia from '#material-ui/core/CardMedia';
import CardActions from '#material-ui/core/CardActions';
import Collapse from '#material-ui/core/Collapse';
import Avatar from '#material-ui/core/Avatar';
import IconButton from '#material-ui/core/IconButton';
import MoreVertIcon from '#material-ui/icons/MoreVert';
import FormControlLabel from '#material-ui/core/FormControlLabel';
import Menu from '#material-ui/core/Menu';
import MenuItem from '#material-ui/core/MenuItem';
import { create } from 'jss';
import rtl from 'jss-rtl';
import { StylesProvider, jssPreset } from '#material-ui/core/styles';
const jss = create({ plugins: [...jssPreset().plugins, rtl()] });
const useStyles = makeStyles((theme) => ({
stock: {
marginBottom: '1rem'
},
Button: {
...theme.typography.button,
padding: '.3rem',
minWidth: 10,
},
media: {
height: 0,
paddingTop: '56.25%', // 16:9
},
title: {
backgroundColor: '#D8D8D8'
},
grid: {
padding: '0'
},
cardFont:{
...theme.typography.body,
textAlign:'right',
marginTop:'.8rem',
marginRight:'1rem'
},productName:{
...theme.typography.body,
textAlign:'right',
},
cardButton:{
marginLeft:'1.4rem'
}
}));
const Cardd = ({
product,
showViewProductButton = true,
showAddToCartButton = true,
cartUpdate = false,
showRemoveProductButton = false,
setRun = f => f,
run = undefined
// changeCartSize
}) => {
const [redirect, setRedirect] = useState(false);
const [count, setCount] = useState(product.count);
//material ui
const [anchorEl, setAnchorEl] = React.useState(null);
const handleClick = (event) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
// console.log(price)
const classes = useStyles()
const showViewButton = showViewProductButton => {
return (
showViewProductButton && (
<Link to={`/product/${product._id}`} className="mr-2">
<Button className={classes.Button} size="small" variant="contained">مشاهده محصول</Button>
</Link>
)
);
};
const addToCart = () => {
// console.log('added');
addItem(product, setRedirect(true));
};
const shouldRedirect = redirect => {
if (redirect) {
return <Redirect to="/cart" />;
}
};
const showAddToCartBtn = showAddToCartButton => {
return (
showAddToCartButton && (
<Button className={classes.Button} size="small" onClick={addToCart} variant="contained" color="primary" disableElevation>
اضافه کردن به سبد
</Button>
)
);
};
const showStock = quantity => {
return quantity > 0 ? (
<Button disabled size="small" className={classes.stock}>موجود </Button>
) : (
<Button className={classes.stock}>ناموجود </Button>
);
};
const handleChange = productId => event => {
setRun(!run); // run useEffect in parent Cart
setCount(event.target.value < 1 ? 1 : event.target.value);
if (event.target.value >= 1) {
updateItem(productId, event.target.value);
}
};
const showCartUpdateOptions = cartUpdate => {
return (
cartUpdate && (
<div>
<div className="input-group mb-3">
<div className="input-group-prepend">
<span className="input-group-text">تعداد</span>
</div>
<input type="number" className="form-control" value={count} onChange={handleChange(product._id)} />
</div>
</div>
)
);
};
const showRemoveButton = showRemoveProductButton => {
return (
showRemoveProductButton && (
<Button className={classes.Button} size="small" variant="contained" color="secondary" disableElevation
onClick={() => {
removeItem(product._id);
setRun(!run); // run useEffect in parent Cart
}}
>
حذف محصول
</Button>
)
);
};
return (
<Grid container direction='column' >
<Grid item >
<Card style={{margin:'1rem'}}>
<Grid item className={classes.title}>
<Typography className={classes.productName} variant='h6'>
{product.name}
</Typography>
</Grid>
<CardHeader
avatar={
<Avatar alt="Remy Sharp" src={logo} className={classes.green}>
</Avatar>
}
action={
<IconButton aria-label="settings">
<MoreVertIcon />
</IconButton>
}
title="روغنک"
subheader="September 14, 2016"
/>
<CardContent className={classes.grid} >
{shouldRedirect(redirect)}
<ShowImage item={product} url="product" />
<StylesProvider jss={jss}>
<Typography className={classes.cardFont} variant="body2" component="p">
{product.description.substring(0, 100)}
</Typography>
</StylesProvider>
<div>
<Button aria-controls="simple-menu" aria-haspopup="true" onClick={handleClick}>
Open Menu
</Button>
<Menu
id="simple-menu"
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl)}
onClose={handleClose}
>
<MenuItem onClick={handleClose}>Profile</MenuItem>
<MenuItem onClick={handleClose}>My account</MenuItem>
<MenuItem onClick={handleClose}>Logout</MenuItem>
</Menu>
</div>
<Typography className={classes.cardFont} variant="body2" component="p">
$یک لیتر {product.price}
</Typography>
<Typography className={classes.cardFont} variant="body2" component="p">
$نیم لیتر {product.price2}
</Typography>
<Typography className={classes.cardFont} variant="body2" component="p">
Category: {product.category && product.category.name}
</Typography>
<Typography className={classes.cardFont} variant="body2" component="p">
Added on {moment(product.createdAt).fromNow()}
</Typography>
<Typography className={classes.cardFont} variant="body2" component="p">
{showStock(product.quantity)}
</Typography>
<br />
<Grid container >
<Grid item className={classes.cardButton} >
{showViewButton(showViewProductButton)}
</Grid>
<Grid item className={classes.cardButton}>
{showAddToCartBtn(showAddToCartButton)}
</Grid>
<Grid item className={classes.cardButton}>
{showRemoveButton(showRemoveProductButton)}
</Grid>
</Grid>
{showCartUpdateOptions(cartUpdate)}
</CardContent>
</Card>
</Grid>
</Grid>
// <div className="card ">
// <div className="card-header card-header-1 ">{product.name}</div>
// <div className="card-body">
// {shouldRedirect(redirect)}
// <ShowImage item={product} url="product" />
// <p className="card-p mt-2">{product.description.substring(0, 100)} </p>
// <p className="card-p black-10">$ {product.price}</p>
// <p className="black-9">Category: {product.category && product.category.name}</p>
// <p className="black-8">Added on {moment(product.createdAt).fromNow()}</p>
// {showStock(product.quantity)}
// <br />
// {showViewButton(showViewProductButton)}
// {showAddToCartBtn(showAddToCartButton)}
// {showRemoveButton(showRemoveProductButton)}
// {showCartUpdateOptions(cartUpdate)}
// </div>
// </div>
);
};
export default Cardd;
CartHelper component
export const addItem = (item = [], count = 0, next = f => f) => {
let cart = [];
if (typeof window !== 'undefined') {
if (localStorage.getItem('cart')) {
cart = JSON.parse(localStorage.getItem('cart'));
}
cart.push({
...item,
count: 1
});
// remove duplicates
// build an Array from new Set and turn it back into array using Array.from
// so that later we can re-map it
// new set will only allow unique values in it
// so pass the ids of each object/product
// If the loop tries to add the same value again, it'll get ignored
// ...with the array of ids we got on when first map() was used
// run map() on it again and return the actual product from the cart
cart = Array.from(new Set(cart.map(p => p._id))).map(id => {
return cart.find(p => p._id === id);
});
localStorage.setItem('cart', JSON.stringify(cart));
next();
}
};
export const itemTotal = () => {
if (typeof window !== 'undefined') {
if (localStorage.getItem('cart')) {
return JSON.parse(localStorage.getItem('cart')).length;
}
}
return 0;
};
export const getCart = () => {
if (typeof window !== 'undefined') {
if (localStorage.getItem('cart')) {
return JSON.parse(localStorage.getItem('cart'));
}
}
return [];
};
export const updateItem = (productId, count) => {
let cart = [];
if (typeof window !== 'undefined') {
if (localStorage.getItem('cart')) {
cart = JSON.parse(localStorage.getItem('cart'));
}
cart.map((product, i) => {
if (product._id === productId) {
cart[i].count = count;
}
});
localStorage.setItem('cart', JSON.stringify(cart));
}
};
export const removeItem = productId => {
let cart = [];
if (typeof window !== 'undefined') {
if (localStorage.getItem('cart')) {
cart = JSON.parse(localStorage.getItem('cart'));
}
cart.map((product, i) => {
if (product._id === productId) {
cart.splice(i, 1);
}
});
localStorage.setItem('cart', JSON.stringify(cart));
}
return cart;
};
export const emptyCart = next => {
if (typeof window !== 'undefined') {
localStorage.removeItem('cart');
next();
}
};
I am pushing to an array
options.push(
{
value: <Adrress x={edge.node.location.lon} y={edge.node.location.lat} />,
label: <Adrress x={edge.node.location.lon} y={edge.node.location.lat} />
})
But always When I need this array it refreshes and I get at the start - '' and then actual data, I need to get once to interact with its.
export default function DataFteching({ x, y }) {
const [adrress, setAdrress] = useState(null)
const [loading, setLoading] = useState(true)
const region = /place/
useEffect(() => {
async function FtechData() {
const token = 'pk.eyJ1IjoiYW5kcmlpbXNuIiwiYSI6ImNrZGYzZ200YTJudXQyeHNjMjk2OTk2bjUifQ.njqMX6x6U946yjJdWwA7mA';
await axios.get(`https://api.mapbox.com/geocoding/v5/mapbox.places/${x},${y}.json?access_token=${token}`)
.then(res => {
// console.log(res.data.features.find(place => place.id.match(region)).text)
setAdrress(res.data)
})
.catch(err => console.log(err))
.finally(() => setLoading(false));
}
FtechData();
}, [])
if (loading) return false;
// console.log({ adrress.features.find(place => place.id.match(region)).text })
console.log(`${(adrress.features.find(place => place.id.match(region)).text)}`)
return `${(adrress.features.find(place => place.id.match(region)).text)}`
}
The Code Sandbox have dependencies error but the solution could be something like this
import React, { useEffect, useState } from "react";
import { Link, graphql, useStaticQuery } from "gatsby";
import Layout from "../components/layout";
import blogStyles from "./Styles/blog.module.scss";
import Head from "../components/head";
import Adrress from "../components/Map/ftechAdrress";
import WithCallbacks from "../components/Search-panel";
const BlogPage = () => {
const [options, setOptions] = useState([]);
const data = useStaticQuery(graphql`
query {
allContentfulBlogPost(
sort: { fields: publishedDate, order: DESC }
filter: { node_locale: { eq: "en-US" } }
) {
edges {
node {
title
slug
publishedDate(formatString: "MMM Do, YYYY")
image {
file {
url
}
}
location {
lat
lon
}
breed
find
}
}
}
}
`);
useEffect(() => {
const tmp = [];
data.allContentfulBlogPost.edges.forEach((edge) => {
tmp.push({
value: (
<Adrress x={edge.node.location.lon} y={edge.node.location.lat} />
),
label: <Adrress x={edge.node.location.lon} y={edge.node.location.lat} />
});
});
setOptions([...tmp]);
}, [data]);
return (
<Layout>
<Head title="Blog" />
<h1>lost pets</h1>
{console.log(options)}
<WithCallbacks options={options} />
<ol className={blogStyles.posts}>
{options.map((edge) => {
const styles = edge.node.image
? `url("${edge.node.image.file.url}")`
: `url("https://cdn.pixabay.com/photo/2019/07/30/05/53/dog-4372036__340.jpg")`;
return (
<li>
<Link to={`/blog/${edge.node.slug}`}>
<div
style={{ backgroundColor: "pink", backgroundImage: styles }}
>
<h2>{edge.node.title}</h2>
<p>{edge.node.publishedDate}</p>
<p>Порода: {edge.node.breed}</p>
<p>
Статус: <span>{edge.node.find ? "Найден" : "Потерян"}</span>
</p>
<p>
city:{" "}
<Adrress
x={edge.node.location.lon}
y={edge.node.location.lat}
/>
</p>
</div>
</Link>
</li>
);
})}
</ol>
</Layout>
);
};
export default BlogPage;
const options = []
const region = /place/
data.allContentfulBlogPost.edges.forEach(async (edge) => {
await fetch(`https://api.mapbox.com/geocoding/v5/mapbox.places/${edge.node.location.lon},${edge.node.location.lat}.json?access_token=${token}`)
.then(response => response.json())
.then(json => options.push({
value: json.features.find(place => place.id.match(region)).text,
label: json.features.find(place => place.id.match(region)).text
}))
console.log(options)
}
)