Error of GET http://localhost:3000/users/myproducts/undefined 404 (Not Found) - http-status-code-404

I have a issue about bad request that I have not find any method for solving.
Here is my code for creating a page which contains app bar on the top and it will gather the data from MongoDB users. There is a array defined to users called purchased which contains the ids of products of user bought. main purpose of the code will be take those ids and list them as product cards in the page.
myProducts.js
import * as React from "react";
import { useParams } from "react-router-dom";
import ListPurchase from "../Components/Purchased/listmyPurchase";
import AppBar from "../Components/Navbar/appbar";
export default function ActiveBids() {
const { email } = useParams();
return (
<>
<AppBar></AppBar>
<ListPurchase>email={email}</ListPurchase>
</>
);
}
I think listmyPurchase is listing the products, fetches a user's purchase history from a server using the user's email address. It uses the Axios library to make an HTTP GET request to the server and then parses the response to extract the purchase history data, which it uses to render a list of purchased items. The notEmpty function is used to check if the response data is empty
listmyPurchase.js
import * as React from 'react';
import { Box, Container, CircularProgress, Typography } from '#mui/material';
import serverURI from '../../Constants/connection';
import axios from 'axios';
import PurchasedItems from '../Purchased/myPurchase';
export default function ListPurchase(props) {
const email = props.email;
// console.log(email);
let uri = serverURI + '/users/myproducts/';
const [message, setMessage] = React.useState([{}]);
const [loading, setLoading] = React.useState(true);
React.useEffect(() => {
var config = {
method: 'get',
url: uri + email,
headers: {
'Content-Type': 'application/json',
},
};
console.log(uri);
axios(config)
.then((response) => {
console.log(response.data.message);
setMessage(response.data.message);
setLoading(false);
})
.catch((error) => {
console.log(error);
});
}, [email, uri]);
function notEmpty(obj) {
return Object.keys(obj).length === 0;
}
return (
<Container sx={{ mt: 5, mb: 5 }}>
{/* <Divider></Divider> */}
{loading ? (
<Box sx={{ display: 'flex', justifyContent: 'center', mt: 30 }}>
<CircularProgress />
</Box>
) : (
<Box>
{notEmpty(message[0]) ? (
<Box sx={{ display: 'flex', justifyContent: 'center', mt: 30 }}>
<Typography fontWeight={600}>No active bid history.</Typography>
</Box>
) : (
<Box
sx={{
display: 'flex',
flexDirection: 'column',
columnGap: 3,
rowGap: 2,
gridTemplateColumns: 'repeat(4, 1fr)',
}}
>
{message.map((product, idx) => (
<PurchasedItems
key={idx}
pid={product._id}
price={product.price}
start_date={product.start_date}
duration={product.duration}
type={product.type}
name={product.name}
owner={product.owner}
image={product.image}
states={product.state}
></PurchasedItems>
))}
</Box>
)}
</Box>
)}
</Container>
);
}
In here I know there is unnecessary part of change the color of text interms of price and who bidded but the only thing I try to manage is the list different products that purchased in terms of bidded by users It is React component that represents a single purchased item. It receives data about the purchased item as props, including the item's name, type, owner, image, and bid price. The component renders this information in a user-friendly format and includes an event handler for clicking on the image or the item's name, which navigates to the product page for the item. The states prop is used to determine the color of the bid price (green if the bid is active, red if it is not). The useNavigate hook from the react-router-dom library is used to handle navigation to the product page.
myPurchase.js
import * as React from 'react';
import { Box, Typography } from '#mui/material';
import { Container } from '#mui/material';
import { useNavigate } from 'react-router-dom';
export default function PurchasedItems(props) {
const pid = props.pid;
// console.log(pid);
const type = props.type || 'test';
const name = props.name || 'test';
const owner = props.owner || 'test';
const image =
props.image ||
'https://assets.adidas.com/images/w_600,f_auto,q_auto/49808757050946de8bedae29011926b5_9366/Manchester_United_22-23_Home_Jersey_Red_H13881_21_model.jpg';
const price = props.price;
const duration = Number(props.duration) / 1000;
const start_date = Number(props.start_date) / 1000;
const currentDate = Math.floor(Date.now() / 1000);
const remainingTime = duration - (currentDate - start_date);
const states = props.states;
const [currentRemaningTime, setRemainingTime] = React.useState(remainingTime);
const navigate = useNavigate();
const handleProductPage = () => {
navigate(`/product/${pid}`);
};
return (
<Container>
<Box sx={{ display: 'flex', justifyContent: 'center' }}>
{' '}
<Box
sx={{
width: '60%',
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
p: 3,
}}
>
<Box sx={{ display: 'flex', direction: 'row', alignItems: 'center' }}>
<Box>
<img
onClick={handleProductPage}
component="img"
src={image}
alt="Paella dish"
style={{ width: 200, height: 200, m: 3 }}
/>
</Box>
<Box onClick={handleProductPage} sx={{ ml: 5 }}>
<Typography color="text.primary" sx={{ fontWeight: 700 }}>
{name}
</Typography>
<Typography color="text.primary" sx={{ fontWeight: 500 }}>
{type}
</Typography>
<Typography color="text.primary" sx={{ fontWeight: 500 }}>
{owner}
</Typography>
</Box>
</Box>
<Box
onClick={handleProductPage}
sx={{ display: 'flex', alignItems: 'center' }}
>
<Typography sx={{ color: 'black', fontWeight: 700 }}>
{`Your bid:`}
</Typography>
{states ? (
<Typography sx={{ color: 'green', fontWeight: 700 }}>
{`${price}$`}
</Typography>
) : (
<Typography sx={{ color: 'red', fontWeight: 700 }}>
{`${price}$`}
</Typography>
)}
</Box>
</Box>
</Box>
</Container>
);
}
App.js
import "./App.css";
import Signin from "./Views/signin";
import Signup from "./Views/signup";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import Profile from "./Views/profile";
// import Test from "./Views/test";
import Search from "./Views/search";
import HomePage from "./Views/homepage";
import Product from "./Views/product";
import AdminPage from "./Views/adminpage";
import ActiveBids from "./Views/activebid";
import MyProducts from "./Views/myProducts";
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/myproducts/:email" element={<MyProducts />} />
</Routes>
</BrowserRouter>
);
}
export default App;
users.js
var express = require("express");
var router = express.Router();
const userModel = require("../models/user.model");
let userController = require("../controller/user.controller");
router.get("/myproducts/:email", userController.getMyPurchase);
module.exports = router;
user.controller.js
const express = require('express');
var router = express.Router();
let mongoose = require('mongoose');
let auth = require('../controller/auth');
let bcrypt = require('bcryptjs');
const { Schema } = mongoose;
const { MongoClient, MongoGridFSChunkError, ObjectId } = require('mongodb');
const userModel = require('../models/user.model');
const teamModel = require('../models/team.model');
const catchAsync = require('./../utils/catchAsync');
const productModel = require('../models/product.model');
const bidModel = require('../models/bid.model');
const mailgun = require('mailgun-js');
exports.getMyPurchase = (req, res, next) => {
let email = req.params.email;
// Find the user with the specified email address
userModel
.findOne({ email: email })
.then((user) => {
// Find the purchased items for the user
productModel
.find({
_id: { $in: user.purchased },
open: true,
})
.then((products) => {
// Send the purchased items as a response
res.send({
message: products,
});
})
.catch((error) => {
// Handle any errors that occurred during the query
next(error);
});
})
.catch((error) => {
// Handle any errors that occurred during the query
next(error);
});
};
``;
I cannot find the reason of "GET http://localhost:3000/users/myproducts/undefined 404 (Not Found)"

Related

Refine dashboard showing error---Error: SyntaxError: Unexpected token, expected ";" (7:22)

image showing the error
I tried to implement the google login in my react app using refine. I was trying to make a react app using refine and other packages.
I was following a course on youtube, i almost followed the youtuber till this step but my code was giving error while his wasn't.
But this error popped up.
The below is my code.
import { useEffect, useRef } from "react";
import { useLogin } from "#pankod/refine-core";
import { Container, Box } from "#pankod/refine-mui";
import { yariga } from "../assets";
import { CredentialResponse } from "../interfaces/google";
export const Login: React.FC = () => {
const { mutate: login } = useLogin<CredentialResponse>();
const GoogleButton = (): JSX.Element => {
const divRef = useRef<HTMLDivElement>(null);
useEffect(() => {
if (typeof window === "undefined" || !window.google || !divRef.current) {
return;
}
try {
window.google.accounts.id.initialize({
ux_mode: "popup",
client_id: process.env.REACT_APP_GOOGLE_CLIENT_ID,
callback: async (res: CredentialResponse) => {
if (res.credential) {
login(res);
}
},
});
window.google.accounts.id.renderButton(divRef.current, {
theme: "filled_blue",
size: "medium",
type: "standard",
});
} catch (error) {
console.log(error);
}
}, []); // you can also add your client id as dependency here
return <div ref={divRef} />;
};
return (
<Box
component="div"
sx={{ backgroundColor: "#FCFCFC" }}
>
<Container
component="main"
maxWidth="xs"
sx={{
display: "flex",
flexDirection: "column",
justifyContent: "center",
height: "100vh",
}}
>
<Box
sx={{
display: "flex",
justifyContent: "center",
flexDirection: "column",
alignItems: "center",
}}
>
<div>
<img src={yariga} alt="Yariga Logo" />
</div>
<Box mt={4}>
<GoogleButton />
</Box>
</Box>
</Container>
</Box>
);
};

I want to navigate to home page upon successfull authentication

I am working on a next.js theme. I want to navigate to the "dashboards/analytics" page upon successfull authentication. we are using JWT based authentication. Authentication is done. but i could not navigate to the dashboards page.I really could not understand what is wrong in this code. Also i am getting a "Password is required error" even after passing a value. but it is not effecting the login function(i was able to login though, with the same password value). i tried commenting out the "yup resolver" code. but it didnt show any error when i clicked login button without a password(but login was not successfull). Kindly someone help me to fix these issues.
AuthContext.js file is as shown below
// ** React Imports
import { createContext, useEffect, useState } from 'react'
// ** Next Import
import {useRouter} from 'next/router'
// ** Axios
import axios from 'axios'
// ** Config
import authConfig from 'src/configs/auth'
// ** Defaults
const defaultProvider={
user: null,
loading: true,
setUser: () => null,
setLoading: () => Boolean,
isInitialized: false,
login: (token) => {},
logout: () => Promise.resolve(),
setIsInitialized: () => Boolean,
register: () => Promise.resolve(),
token:'',
};
const AuthContext = createContext(defaultProvider)
const AuthProvider = ({ children }) => {
// ** States
const [user, setUser] = useState(defaultProvider.user)
const [loading, setLoading] = useState(defaultProvider.loading)
const [isInitialized, setIsInitialized] = useState(defaultProvider.isInitialized)
const [token,setToken]=useState(defaultProvider.token)
// ** Hooks
const router = useRouter()
useEffect(() => {
const initAuth = async () => {
setIsInitialized(true)
const storedToken = window.localStorage.getItem(authConfig.storageTokenKeyName)
if (storedToken) {
setLoading(true)
await axios
.get(authConfig.meEndpoint, {
headers: {
Authorization: storedToken
}
})
.then(async response => {
setLoading(false)
setUser({ ...response.data.userData })
})
} else {
setLoading(false)
}
}
initAuth()
}, [])
const handleLogin=(token)=>{
setToken(token);
router.push('/dashboards/analytics');
}
const handleLogout = () => {
setUser(null)
setIsInitialized(false)
window.localStorage.removeItem('userData')
window.localStorage.removeItem(authConfig.storageTokenKeyName)
router.push('/login')
}
const handleRegister = (params, errorCallback) => {
axios
.post(authConfig.registerEndpoint, params)
.then(res => {
if (res.data.error) {
if (errorCallback) errorCallback(res.data.error)
} else {
handleLogin({ email: params.email, password: params.password })
}
})
.catch(err => (errorCallback ? errorCallback(err) : null))
}
const values = {
user,
loading,
setUser,
setLoading,
isInitialized,
setIsInitialized,
login: handleLogin,
logout: handleLogout,
register: handleRegister,
token
}
return <AuthContext.Provider value={values}>{children}</AuthContext.Provider>
}
export { AuthContext, AuthProvider }
Login/index.js file is as shown below,
// ** React Imports
import { useState, useContext } from 'react'
import {useRouter} from 'next/router'
// ** Next Imports
import Link from 'next/link'
import axios from 'axios'
// ** MUI Components
import Button from '#mui/material/Button'
import Divider from '#mui/material/Divider'
import Checkbox from '#mui/material/Checkbox'
import TextField from '#mui/material/TextField'
import InputLabel from '#mui/material/InputLabel'
import IconButton from '#mui/material/IconButton'
import Box from '#mui/material/Box'
import FormControl from '#mui/material/FormControl'
import useMediaQuery from '#mui/material/useMediaQuery'
import OutlinedInput from '#mui/material/OutlinedInput'
import { styled, useTheme } from '#mui/material/styles'
import FormHelperText from '#mui/material/FormHelperText'
import InputAdornment from '#mui/material/InputAdornment'
import Typography from '#mui/material/Typography'
import MuiFormControlLabel from '#mui/material/FormControlLabel'
// ** Icons Imports
import Google from 'mdi-material-ui/Google'
import Github from 'mdi-material-ui/Github'
import Twitter from 'mdi-material-ui/Twitter'
import Facebook from 'mdi-material-ui/Facebook'
import EyeOutline from 'mdi-material-ui/EyeOutline'
import EyeOffOutline from 'mdi-material-ui/EyeOffOutline'
// ** Third Party Imports
import * as yup from 'yup'
import { useForm, Controller } from 'react-hook-form'
import { yupResolver } from '#hookform/resolvers/yup'
// ** Hooks
import { useAuth } from 'src/hooks/useAuth'
import useBgColor from 'src/#core/hooks/useBgColor'
import { useSettings } from 'src/#core/hooks/useSettings'
// ** Configs
import themeConfig from 'src/configs/themeConfig'
// ** Layout Import
import BlankLayout from 'src/#core/layouts/BlankLayout'
// ** Demo Imports
import FooterIllustrationsV2 from 'src/views/pages/auth/FooterIllustrationsV2'
import { AuthContext } from 'src/context/AuthContext'
// ** Styled Components
const LoginIllustrationWrapper = styled(Box)(({ theme }) => ({
padding: theme.spacing(20),
paddingRight: '0 !important',
[theme.breakpoints.down('lg')]: {
padding: theme.spacing(10)
}
}))
const LoginIllustration = styled('img')(({ theme }) => ({
maxWidth: '48rem',
[theme.breakpoints.down('lg')]: {
maxWidth: '35rem'
}
}))
const RightWrapper = styled(Box)(({ theme }) => ({
width: '100%',
[theme.breakpoints.up('md')]: {
maxWidth: 450
}
}))
const BoxWrapper = styled(Box)(({ theme }) => ({
[theme.breakpoints.down('xl')]: {
width: '100%'
},
[theme.breakpoints.down('md')]: {
maxWidth: 400
}
}))
const TypographyStyled = styled(Typography)(({ theme }) => ({
fontWeight: 600,
marginBottom: theme.spacing(1.5),
[theme.breakpoints.down('md')]: { marginTop: theme.spacing(8) }
}))
const LinkStyled = styled('a')(({ theme }) => ({
fontSize: '0.875rem',
textDecoration: 'none',
color: theme.palette.primary.main
}))
const FormControlLabel = styled(MuiFormControlLabel)(({ theme }) => ({
'& .MuiFormControlLabel-label': {
fontSize: '0.875rem',
color: theme.palette.text.secondary
}
}))
const schema = yup.object().shape({
username: yup.string().required(),
password: yup.string().min(5 ).required()
})
const LoginPage = () => {
const [showPassword, setShowPassword] = useState(false)
const [username,setUsername]=useState('');
const [password,setPassword]=useState('');
//const [errMsg,setErrMsg]=useState('');
// ** Hooks
const auth = useContext(AuthContext);
const theme = useTheme()
const router=useRouter();
const bgClasses = useBgColor()
const {
settings: { skin }
} = useSettings()
const {
control,
setError,
//handleSubmit,
formState: { errors }
} = useForm({
//defaultValues,
mode: 'onBlur',
resolver: yupResolver(schema)
})
// ** Vars
const hidden = useMediaQuery(theme.breakpoints.down('md'))
const handleSubmit=(e)=>{
e.preventDefault();
fetch(
'url',
{
method:'POST',
body:JSON.stringify({
username:username,
password:password,
}),
headers: {
'Content-Type':'application/json',
'X-Correlation-ID':'123456',
'Source-ID':'abc123',
}
}).then(res =>{
if(res.ok){
return res.json();
}
else{
return res.json().then(data=> {
let errorMessage="Authentication Failed";
throw new Error(errorMessage);
});
}
}).then(data=>{
auth.login(data.response.accessToken);
}).catch(err=>{
alert(err.message);
});
}
return (
<Box className='content-right'>
{!hidden ? (
<Box sx={{ flex: 1, display: 'flex', position: 'relative', alignItems: 'center', justifyContent: 'center' }}>
<LoginIllustrationWrapper>
<LoginIllustration
alt='login-illustration'
src={`/images/pages/auth-v2-login-illustration-${theme.palette.mode}.png`}
/>
</LoginIllustrationWrapper>
<FooterIllustrationsV2 />
</Box>
) : null}
<RightWrapper sx={skin === 'bordered' && !hidden ? { borderLeft: `1px solid ${theme.palette.divider}` } : {}}>
<Box
sx={{
p: 12,
height: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: 'background.paper'
}}
>
<BoxWrapper>
<Box
sx={{
top: 30,
left: 40,
display: 'flex',
position: 'absolute',
alignItems: 'center',
justifyContent: 'center'
}}
>
<Typography
variant='h6'
sx={{
ml: 3,
lineHeight: 1,
fontWeight: 600,
textTransform: 'uppercase',
fontSize: '1.5rem !important'
}}
>
{themeConfig.templateName}
</Typography>
</Box>
<Box sx={{ mb: 6 }}>
<TypographyStyled variant='h5'>Welcome to {themeConfig.templateName}! 👋🏻</TypographyStyled>
<Typography variant='body2'>Please sign-in to your account and start the adventure</Typography>
</Box>
<form noValidate autoComplete='off' onSubmit={handleSubmit}>
<FormControl fullWidth sx={{ mb: 4 }}>
<Controller
name='Username'
control={control}
rules={{ required: true }}
render={({ field: { value, onChange, onBlur } }) => (
<TextField
autoFocus
label='Username'
value={value}
onBlur={onBlur}
//onChange={onChange}
onChange={(e)=> setUsername(e.target.value)}
error={Boolean(errors.user)}
// placeholder='admin#materio.com'
/>
)}
/>
{errors.user && <FormHelperText sx={{ color: 'error.main' }}>{errors.user.message}</FormHelperText>}
</FormControl>
<FormControl fullWidth>
<InputLabel htmlFor='auth-login-v2-password' error={Boolean(errors.password)}>
Password
</InputLabel>
<Controller
name='password'
control={control}
rules={{ required: true }}
render={({ field: { value,onChange, onBlur } }) => (
<OutlinedInput
value={value}
onBlur={onBlur}
label='Password'
//onChange={onChange}
onChange={(e)=> setPassword(e.target.value)}
id='auth-login-v2-password'
error={Boolean(errors.password)}
type={showPassword ? 'text' : 'password'}
endAdornment={
<InputAdornment position='end'>
<IconButton
edge='end'
onMouseDown={e => e.preventDefault()}
onClick={() => setShowPassword(!showPassword)}
>
{showPassword ? <EyeOutline /> : <EyeOffOutline />}
</IconButton>
</InputAdornment>
}
/>
)}
/>
{errors.password && (
<FormHelperText sx={{ color: 'error.main' }} id=''>
{errors.password.message}
</FormHelperText>
)}
</FormControl>
<Box
sx={{ mb: 4, display: 'flex', alignItems: 'center', flexWrap: 'wrap', justifyContent: 'space-between' }}
>
<FormControlLabel control={<Checkbox />} label='Remember Me' />
<Link passHref href='/forgot-password'>
<LinkStyled>Forgot Password?</LinkStyled>
</Link>
</Box>
<Button fullWidth size='large' type='submit' variant='contained' sx={{ marginBottom: 7 }}>
Login
</Button>
<Box sx={{ display: 'flex', alignItems: 'center', flexWrap: 'wrap', justifyContent: 'center' }}>
<Typography variant='body2' sx={{ marginRight: 2 }}>
New on our platform?
</Typography>
<Typography variant='body2'>
<Link passHref href='/register'>
<LinkStyled>Create an account</LinkStyled>
</Link>
</Typography>
</Box>
<Divider sx={{ my: 5 }}>or</Divider>
<Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<Link href='/' passHref>
<IconButton component='a' onClick={e => e.preventDefault()}>
<Facebook sx={{ color: '#497ce2' }} />
</IconButton>
</Link>
<Link href='/' passHref>
<IconButton component='a' onClick={e => e.preventDefault()}>
<Twitter sx={{ color: '#1da1f2' }} />
</IconButton>
</Link>
<Link href='/' passHref>
<IconButton component='a' onClick={e => e.preventDefault()}>
<Github
sx={{ color: theme => (theme.palette.mode === 'light' ? '#272727' : theme.palette.grey[300]) }}
/>
</IconButton>
</Link>
<Link href='/' passHref>
<IconButton component='a' onClick={e => e.preventDefault()}>
<Google sx={{ color: '#db4437' }} />
</IconButton>
</Link>
</Box>
</form>
</BoxWrapper>
</Box>
</RightWrapper>
</Box>
)
}
LoginPage.getLayout = page => <BlankLayout>{page}</BlankLayout>
LoginPage.guestGuard = true
export default LoginPage

Dynamic URL in React

I'm working on a React project with Redux and I'm consuming a Rest API, I need to implement a functionality where when I select a project from a list and I need to load the project ID in the URL and direct to another screen where a sidebar with the options is loaded. navigation of this project.
Example: Layout
I managed to load the project's Id in the URL and retrieve this ID in the project's home screen, the problem is to store the project's Id and set this ID in the next selected URLs, for example:
path: '/project/:id/companies'
path: '/project/:id/currencies'
path: '/project/:id/settings'
List of projects:
Capture the project id and arrow the url:
href={`#/project/${row.id}/main`}
Routes:
path: '/project/:id/main',
exact: true,
name: 'projectMain',
component: RequireAuth(ProjectMain),
Retrieve ID in main
import { useParams } from 'react-router-dom';
...
const { id } = useParams();
The problem is in the sidebar, where I load a list of items with the path, I'm not able to pass the project id in this list.
Complementando a pergunta
In Sidebar I'm using useHistory(), the problem is that the path comes static by 'props' through importing a file into my template, as you can see below:
Template
import React from 'react';
import { Grid, makeStyles } from '#material-ui/core';
import {
AppContent,
AppHeader,
SidebarApp,
} from '../components/index';
import itemsProject from '../components/itemsSidebar/itemsProject';
const useStyles = makeStyles(theme => ({
appContent: {
paddingLeft: 240,
width: '100%',
backgroundColor: theme.palette.background.paper,
},
}));
const ProjectLayout = () => {
const classes = useStyles();
return (
<div className={classes.appContent}>
<AppHeader />
<Grid container direction="row">
<SidebarApp items={itemsProject} />
<AppContent />
</Grid>
</div>
);
};
export default ProjectLayout;
Sidebar:
/* eslint-disable react/jsx-no-duplicate-props */
import React from 'react';
import List from '#material-ui/core/List';
import ListItem from '#material-ui/core/ListItem';
import Divider from '#material-ui/core/Divider';
import ExpandMoreIcon from '#material-ui/icons/ExpandMore';
import ExpandLessIcon from '#material-ui/icons/ExpandLess';
import Collapse from '#material-ui/core/Collapse';
import {
alpha,
Box,
Card,
ListSubheader,
makeStyles,
Typography,
} from '#material-ui/core';
import { useHistory, useLocation, useParams } from 'react-router-dom';
import translate from '../providers/i18n/translate';
const useStyles = makeStyles(theme => ({
sidebar: {
background: theme.palette.background.dark,
width: 240,
height: '100vh',
border: '1px solid rgba(0, 0, 0, 0.1)',
display: 'flex',
flexDirection: 'column',
position: 'absolute',
paddingTop: 64,
top: 0,
left: 0,
},
sidebarItem: {
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
},
sidebarItemContent: {
whiteSpace: 'nowrap',
textOverflow: 'ellipsis',
overflow: 'hidden',
display: 'flex',
alignItems: 'center',
width: '100%',
},
sidebarItemIcon: {
marginRight: 6,
},
sidebarItemText: {
width: '100%',
},
sidebarItemExpandArrow: {
fontSize: '1.2rem !important',
},
sidebarItemExpandArrowExpanded: {
fontSize: '1.2rem !important',
color: theme.palette.primary.main,
fontWeight: 'bold',
},
active: {
background: alpha(theme.palette.primary.light, 0.2),
},
}));
function SidebarItem({ depthStep = 10, depth = 0, expanded, item, ...rest }) {
const [collapsed, setCollapsed] = React.useState(true);
const { label, items, Icon, onClick: onClickProp } = item;
const classes = useStyles();
const history = useHistory();
const location = useLocation();
function toggleCollapse() {
setCollapsed(prevValue => !prevValue);
}
function onClick(e) {
if (Array.isArray(items)) {
toggleCollapse();
}
if (onClickProp) {
onClickProp(e, item);
history.push(item.path);
}
}
let expandIcon;
if (Array.isArray(items) && items.length) {
expandIcon = !collapsed ? (
<>
<ExpandLessIcon className={classes.sidebarItemExpandArrowExpanded} />
</>
) : (
<ExpandMoreIcon className={classes.sidebarItemExpandArrow} />
);
}
return (
<>
<ListItem
className={classes.sidebarItem}
onClick={onClick}
button
dense
className={location.pathname === item.path ? classes.active : null}
{...rest}
>
<div
style={{ paddingLeft: depth * depthStep }}
className={classes.sidebarItemContent}
>
{Icon && (
<Icon
className={classes.sidebarItemIcon}
fontSize="small"
color="primary"
/>
)}
<div className={classes.sidebarItemText}>{label}</div>
</div>
{expandIcon}
</ListItem>
<Collapse in={!collapsed} timeout="auto" unmountOnExit>
{Array.isArray(items) ? (
<List disablePadding dense>
{items.map((subItem, index) => (
<React.Fragment key={`${subItem.name}${index}`}>
{subItem === 'divider' ? (
<Divider style={{ margin: '6px 0' }} />
) : (
<SidebarItem
depth={depth + 1}
depthStep={depthStep}
item={subItem}
/>
)}
</React.Fragment>
))}
</List>
) : null}
</Collapse>
</>
);
}
function Sidebar({ items, depthStep, depth, expanded }) {
const classes = useStyles();
const { key } = useParams();
return (
<Card elevation={0} className={classes.sidebar}>
<List
disablePadding
dense
subheader={
<ListSubheader component="div" id="nested-list-subheader">
{translate('sidebarMenuSettings')}
<Typography>
<Box>{key}</Box>
</Typography>
</ListSubheader>
}
>
{items.map((sidebarItem, index) => (
<React.Fragment key={`${sidebarItem.name}${index}`}>
{sidebarItem === 'divider' ? (
<Divider style={{ margin: '6px 0' }} />
) : (
<SidebarItem
depthStep={depthStep}
depth={depth}
expanded={expanded}
item={sidebarItem}
/>
)}
</React.Fragment>
))}
</List>
</Card>
);
}
export default Sidebar;
Sidebar list items
function onClick(e, item) {}
const itemsProject = [
{
name: 'companies',
label: translate('sidebarProjectCompanies'),
Icon: CompanyIcon,
path: '/project/:id/companies',
onClick,
}
{
name: 'currencies',
label: translate('sidebarProjectCurrencies'),
Icon: CurrencyIcon,
path: '/project/:id/currencies',
onClick,
}
];
export default itemsProject;
How can I pass the ID variable on the Sidebar list items?
I thank you for your help!
You can use ES6 template literals as follows.
path: `/project/${id}/companies`
Since you already defined your path, you just need to use useHistory and navigate to the new link
import { useHistory } from 'react-router';
...
const history = useHistory();
...
// call this whenever you want to navigate
history.push(`/project/${id}/currencies`);

Next js: Error: Objects are not valid as a React child (found: Error: Response not successful: Received status code 401)

This app shows Github issues with graphql API.
I didn't change anything after finishing the app but I got this error.
I used Next js, Typescript, Material UI, Tailwind css and GraphQL for this project.
Index Component
import React, { useState } from "react"
import { Typography, Container, makeStyles } from "#material-ui/core"
import SearchBar from "../components/SearchBar/SearchBar"
import RepositoryList from "../components/RepositoryList/RepositoryList"
import Head from "next/head"
const useStyles = makeStyles({
title: {
marginTop: "1rem",
marginBottom: "1rem",
textAlign: "center",
},
})
const App = () => {
const classes = useStyles()
const [searchTerm, setSearchTerm] = useState<string>("")
return (
<>
<Head>
<title>GraphQL Github Client</title>
</Head>
<Container maxWidth={"sm"}>
<div className="mt-10 mb-5">
<Typography variant={"h3"} className={classes.title}>
GraphQL Github Client
</Typography>
</div>
<SearchBar
className="mb-10"
value={searchTerm}
onChange={setSearchTerm}
/>
<RepositoryList searchTerm={searchTerm} />
</Container>
</>
)
}
export default App
RepositoryList Component
import React, { useEffect, useState } from "react"
import { Typography, CircularProgress, makeStyles } from "#material-ui/core"
import { useQuery } from "#apollo/react-hooks"
import { SEARCH_FOR_REPOS } from "../../Queries/queries"
import Repository from "../Repository/Repository"
interface RepositoryListProps {
searchTerm?: string
}
const useStyles = makeStyles({
note: {
marginTop: "1rem",
textAlign: "center",
},
spinnerContainer: {
display: "flex",
justifyContent: "space-around",
marginTop: "1rem",
},
})
const RepositoryList: React.FC<RepositoryListProps> = ({ searchTerm }) => {
const classes = useStyles()
const [expandedRepo, setExpandedRepo] = useState(null)
const { data, loading, error } = useQuery(SEARCH_FOR_REPOS, {
variables: { search_term: searchTerm },
})
useEffect(() => {
setExpandedRepo(null)
}, [data])
if (loading) {
return (
<div className={classes.spinnerContainer}>
<CircularProgress />
</div>
)
}
if (error) {
return (
<Typography
variant={"overline"}
className={classes.note}
component={"div"}
color={"error"}
>
{error}
</Typography>
)
}
if (!data.search.repositoryCount) {
return (
<Typography
variant={"overline"}
className={classes.note}
component={"div"}
>
There are no such repositories!
</Typography>
)
}
return (
<div>
{data.search.edges.map(
(
repo: { edges: { id: number } },
i: string | number | ((prevState: null) => null) | null | any
) => (
<>
<Repository
repo={repo}
expanded={expandedRepo === i}
onToggled={() => setExpandedRepo(i)}
key={repo.edges.id}
/>
</>
)
)}
</div>
)
}
export default RepositoryList
Repository Component
import React from "react"
import {
ExpansionPanel,
ExpansionPanelSummary,
ExpansionPanelDetails,
Typography,
Chip,
makeStyles,
} from "#material-ui/core"
import StarIcon from "#material-ui/icons/Star"
import PeopleIcon from "#material-ui/icons/People"
import IssueList from "../IssueList/IssueList"
const useStyles = makeStyles({
root: {
marginTop: "1rem",
},
summaryContainer: {
flexDirection: "column",
},
summaryHeader: {
display: "flex",
flexDirection: "row",
justifyContent: "space-between",
marginBottom: "1rem",
},
chip: {
marginLeft: "0.5rem",
},
})
interface RepositoryProps {
repo: any
expanded: boolean
onToggled: any
}
const Repository: React.FC<RepositoryProps> = ({
repo,
expanded,
onToggled,
}) => {
const {
node: {
name,
descriptionHTML,
owner: { login },
stargazers: { totalCount: totalStarCount },
},
} = repo
const classes = useStyles()
return (
<ExpansionPanel
expanded={expanded}
onChange={onToggled}
className={classes.root}
>
<ExpansionPanelSummary classes={{ content: classes.summaryContainer }}>
<div className={classes.summaryHeader}>
<Typography variant={"h6"}>{name}</Typography>
<div>
<Chip
label={`by ${login}`}
avatar={<PeopleIcon />}
className={classes.chip}
/>
<Chip
label={totalStarCount}
avatar={<StarIcon />}
className={classes.chip}
/>
</div>
</div>
<Typography
variant={"caption"}
dangerouslySetInnerHTML={{ __html: descriptionHTML }}
component={"div"}
/>
</ExpansionPanelSummary>
<ExpansionPanelDetails>
{expanded && <IssueList repoName={name} repoOwner={login} />}
</ExpansionPanelDetails>
</ExpansionPanel>
)
}
export default Repository
These are my components.
What should I do for fixing this problem?
It looks like the issue is in this spot where you do {error}. I would double check what error actually is but it looks like its an object and not a string like you are using it
<Typography
variant={"overline"}
className={classes.note}
component={"div"}
color={"error"}
>
{error}
</Typography>

Conditional Redirect is not working in react-router-dom

I am using React as Front-End and Firebase for Backend and Database. I login.js component, when I signed in, I expect to redirect it to some formfield component. But, here when I try to Redirect the user after Success message from firebase, Redirection does not work conditionally. I used condition Operator for
redirection. Here's the core for Login.js
import React from 'react';
import { makeStyles } from '#material-ui/core/styles';
import { BrowserRouter as Router, Redirect} from 'react-router-dom';
import { Button, Card, CardContent, Paper, Typography, TextField, Tabs, Tab,FormControl } from '#material-ui/core';
import DateFnsUtils from '#date-io/date-fns';
import {
MuiPickersUtilsProvider,
KeyboardDatePicker,
} from '#material-ui/pickers';
import DataField from './DataField';
import * as firebase from 'firebase';
const useStyles = makeStyles(theme => ({
root: {
flexGrow: 1,
margin: 'auto',
display: 'flex',
flexDirection: 'column',
alignItems: 'center'
},
cards: {
maxWidth: 300,
margin: 'auto',
display: 'flex',
flexDirection: 'column',
alignItems: 'center'
},
formControl: {
padding: theme.spacing(2),
margin: 'auto',
display: 'flex',
flexDirection: 'column',
justigyContent: 'space-around'
},
field: {
minWidth: 250
}
}));
function Login(){
const classes = useStyles();
const [email, setMail] = React.useState();
const [pass, setPass] = React.useState(new Date( '1995-08-18T21:11:54' ));
const auth = firebase.auth();
const handleDateChange = Date => {
const values = Date.toString();
setPass(values)
}
const handlerMail = e => {
setMail(e.target.value);
}
const verify = () => {
const promise = auth.signInWithEmailAndPassword(email, pass);
promise.catch(e => console.log(e.message));
firebase.auth().onAuthStateChanged((user) => {
return ( user ? <Redirect from='/' to='/datafield' /> : <Redirect from='/' to='/' /> )
})
}
return(
<React.Fragment className={classes.root}>
<Card className={classes.cards} elevation={0}>
<Typography variant='h5' color='primary'>Login</Typography>
<CardContent>
<MuiPickersUtilsProvider utils={DateFnsUtils}>
<FormControl className={classes.formControl}>
<TextField id="standard-basic" value={email} onChange={handlerMail} className={classes.field} label="Email" />
<KeyboardDatePicker
margin="normal"
id="date-picker-dialog"
label="Date of Birth"
format="MM/dd/yyyy"
value={pass}
onChange={handleDateChange}
KeyboardButtonProps={{
'aria-label': 'change date',
}}
/>
</FormControl>
</MuiPickersUtilsProvider>
</CardContent>
<Button color='third' onClick={verify} variant='contained'>Login</Button>
</Card>
</React.Fragment>
)
};
export default Login;
I've been working for couples of days to solve it! Not yet found!!!
Can anybody help me to resolve this issue? Thank You!
Try histroy.replace, doc: https://reacttraining.com/react-router/web/api/history
Wrap Login component in withRouter HOC. export default withRouter(Login);
const verify = () => {
const { history } = props;
const promise = auth.signInWithEmailAndPassword(email, pass);
promise.catch(e => console.log(e.message));
firebase.auth().onAuthStateChanged(user => {
if (user) {
history.replace("/datafield");
}
});
};

Resources