How to reload a webpage once routed to using react-router-dom - javascript

Re-asking from a previous questions as this could be a work around.
I have a widget I'm using from a software provider (Mindbody) it needs to load some data using a <script> tag which I have in the head of my app. The page is being routed to using react-router-dom. The problem the js data only loads when you refresh the page.
What is a good method to reloading a page as soon as the page is routed to. I tried window.location.refresh(); but this loads infinite time.
import * as React from 'react';
import { Stack, Box, Typography, Modal, Backdrop } from '#mui/material';
import ButtonV2 from './ButtonV2';
import PurchaseWidget from './PurchaseWidget';
const style = {
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
width: 400,
bgcolor: 'background.paper',
boxShadow: 24,
borderRadius: 3,
transition: "5s ease-in-out"
};
const PurchaseLanding = () => {
const [show, setShow] = React.useState(true);
const handleClose = () => setShow(false);
return (
<div>
<Modal
open={show}
onClose={handleClose}
aria-labelledby="modal-modal-title"
aria-describedby="modal-modal-description"
disableAutoFocus="true"
BackdropComponent={Backdrop}
BackdropProps={{
timeout: 500,
}}>
<Box sx={style}>
<div>
{/* full width image */}
<img style={{borderRadius: "10px 10px 0 0"}} src="https://res.cloudinary.com/djjb1vyjm/image/upload/v1660541084/1_uxhi8p.png" width="100%" alt="" />
</div>
<Box p={2}>
{/* title */}
<Typography align="center" id="modal-modal-title" variant="h5" component="h2">
<span className='space-font-heavy'>Buy your [10-pack]</span>
</Typography>
{/* onboarding message */}
<Stack pb={3} alignItems="center" justifyContent="center" direction="row" spacing={2}>
<Typography px={1} align="center" id="modal-modal-description" sx={{ mt: 2 }}>
<span className='space-font-light'>Once completed download the Mindbody app to add, update, and book your workouts!</span>
</Typography>
</Stack>
{/* button group left/right */}
<Stack direction="row" justifyContent="center" alignItems="center">
<ButtonV2 />
</Stack>
</Box>
</Box>
</Modal>
</div>
);
}
export default PurchaseLanding

Related

Object is possibly "null" in event.target.files in typescript

I want to upload a csv file and later parse it in json format, I have created a state in which i am setting the file using the HTMLEvent Property.I am using typescript I have defined the possible types while defining the state but I am still getting the error.
import {
Box,
Button,
IconButton,
Modal,
Stack,
LinearProgress,
Typography
} from '#mui/material';
import React, { useState } from 'react';
import UploadIcon from '#mui/icons-material/Upload';
import CancelIcon from '#mui/icons-material/Cancel';
import { csvFileParser } from '../../../utils/csvFileParser';
type Props = {};
const BulkServiceUpload = (props: Props) => {
const [openModal, setOpenModal] = useState(false);
const [filename, setFileName] = useState<File | undefined | null>();
console.log(filename);
const style = {
position: 'absolute' as 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
width: 600,
bgcolor: 'background.paper',
border: '2px solid #000',
boxShadow: 24,
borderRadius: '1rem',
borderWidth: 0,
p: 4
};
const serviceMasterParser = async () => {
if (filename === null) {
alert('Please select a file');
} else {
const parsedCSVData: object[] = csvFileParser(filename);
console.log(parsedCSVData);
}
};
return (
<>
<Box>
<Button
variant="contained"
color="success"
onClick={() => setOpenModal(true)}
>
<UploadIcon />
Add Service
</Button>
</Box>
<Modal open={openModal} onClose={() => setOpenModal(false)}>
<Stack padding={3} sx={style} spacing={3}>
<Typography marginY={3} variant="h5" fontWeight={600}>
Upload Service in Bulk
</Typography>
<Box
sx={{
border: 'dashed 1px black',
borderRadius: '1rem',
position: 'relative',
background: '#f0f0f0',
'&:hover': {
backgroundColor: '#EFFAF5'
}
}}
>
<Box position="absolute" width="100%" height="100%" p={3}>
<Box display="flex" justifyContent="center" alignItems="center">
<UploadIcon />
<Typography>Bulk Upload Service Master</Typography>
</Box>
<Typography fontSize="10px" textAlign="center">
only .csv file is supported
</Typography>
</Box>
<input
type="file"
accept=".csv"
onChange={(e: React.FormEvent<HTMLInputElement>) =>
setFileName((e.target as HTMLInputElement).files[0]!)
}
style={{
width: '100%',
height: '150px',
cursor: 'pointer',
opacity: '0'
}}
/>
<Box
p={1}
display={`${filename === null ? 'none' : 'flex'}`}
justifyContent="space-between"
alignItems="center"
sx={{
background: '#f5f5f5',
borderRadius: '15px'
}}
margin={2}
>
<Typography fontSize={14}>{filename?.name!}</Typography>
<IconButton
color="inherit"
aria-label="delete file"
component="label"
onClick={() => {
setFileName(undefined);
}}
>
<CancelIcon fontSize="small" />
</IconButton>
</Box>
{/* <LinearProgress variant="determinate" value={50} /> */}
</Box>
<Button
variant="contained"
color="success"
onClick={() => serviceMasterParser()}
>
<UploadIcon />
Bulk Upload
</Button>
<Button color="success" fullWidth variant="contained">
Add Single Service
</Button>
</Stack>
</Modal>
</>
);
};
export default BulkServiceUpload;
I don't want any initial value for my file.But If i will take useState value empty it will be by default an undefined value. Which is creating this problem. Please let me know how can I solve this .This is my first question so if I have made any mistake my appologies in advance.
Make sure files exists in the target
onChange={(e: React.FormEvent<HTMLInputElement>) =>
setFileName((e.target as HTMLInputElement)?.files?.[0])
}
Hi Everyone I think I have made a small typo error while setting the value of a file
<input
type="file"
accept=".csv"
onChange={(e: React.FormEvent<HTMLInputElement>) =>
setFileName((e.target as HTMLInputElement).files[0]!)
}
style={{
width: '100%',
height: '150px',
cursor: 'pointer',
opacity: '0'
}}
/>
I should have used the ! after files and it resolved the issue
<input
type="file"
accept=".csv"
onChange={(e: React.FormEvent<HTMLInputElement>) =>
setFileName((e.target as HTMLInputElement).files![0])
}
style={{
width: '100%',
height: '150px',
cursor: 'pointer',
opacity: '0'
}}
/>

MUI Collapse component not allowing encapsulated element flex-grow

So I'm a newbie when it comes to React and thought to get familiar with the concepts utilizing mui. I'm creating a nav bar and one of the features is to have a search bar that is initially collapsed and expand once the search icon is pressed. This will also hide the typography element. My issue seems that no matter if I set flexgrow for both collapse or the text input that's being encapsulated the element doesn't seem to grow despite the extra space. I also observed when I set the width of the element using vw it adjusts but the right icons and search bar begin to overlap after minimizing it to a certain point. I wonder if this is a styling issue or whether if transition is incapable of doing this, if it's a styling issue how do I get the text input to expand the needed space?
Navbar.js
import React, { useState } from "react";
import {
AppBar,
Drawer,
Box,
IconButton,
List,
ListItemButton,
ListItemText,
Toolbar,
TextField,
Typography,
Collapse,
} from "#mui/material";
import MenuIcon from "#mui/icons-material/Menu";
import PersonOutlineOutlinedIcon from "#mui/icons-material/PersonOutlineOutlined";
import SearchOutlinedIcon from "#mui/icons-material/SearchOutlined";
import ShoppingBagOutlinedIcon from "#mui/icons-material/ShoppingBagOutlined";
import { createTheme } from "#mui/material";
const Navbar = () => {
const [drawer, setDrawer] = useState(false);
const [drawer2, setDrawer2] = useState(false);
const [clicked, setClicked] = useState(false);
const theme = createTheme({
typography: {
fontFamily: ["Abril Fatface", "cursive"].join(","),
},
});
return (
<AppBar position="fixed" sx={{ height: 70 }} className="navbar">
<Toolbar>
<IconButton onClick={() => setDrawer(!drawer)} className="id">
<MenuIcon fontSize="large"></MenuIcon>
</IconButton>
<Drawer open={drawer} onClose={() => setDrawer(!drawer)}>
<Box sx={{ width: 400, backgroundColor: "red" }}>
<List>
<ListItemButton>
<ListItemText primary="HI" />
</ListItemButton>
</List>
</Box>
</Drawer>
<Collapse orientation="horizontal" in={clicked} timeout={100} unmountOnExit>
<TextField sx={{ flexGrow: 2 }} />
</Collapse>
<Typography
component="a"
variant="h4"
theme={theme}
className="item"
sx={{
color: "black",
flexGrow: 2,
textAlign: "center",
display: clicked ? "none" : "block",
}}
>
APPSTUFF
</Typography>
<IconButton className="id">
<PersonOutlineOutlinedIcon fontSize="large"></PersonOutlineOutlinedIcon>
</IconButton>
<IconButton className="id" onClick={() => setClicked(!clicked)}>
<SearchOutlinedIcon fontSize="large"></SearchOutlinedIcon>
</IconButton>
<IconButton className="id" onClick={() => setDrawer2(!drawer2)}>
<ShoppingBagOutlinedIcon fontSize="large"></ShoppingBagOutlinedIcon>
</IconButton>
<Drawer
open={drawer2}
onClose={() => setDrawer2(!drawer2)}
anchor="right"
>
<Box sx={{ width: 400, backgroundColor: "red" }}>
<List>
<ListItemButton>
<ListItemText primary="HI" />
</ListItemButton>
</List>
</Box>
</Drawer>
</Toolbar>
</AppBar>
);
};
export default Navbar;
NavbarStyle.css
.id {
color: black;
margin-top: 0.5%;
display: flex;
flex-grow: 0;
}
.navbar {
width: 100vw;
box-shadow: none;
background-color: white;
}

useRef takes full control of an outer component instead of the component being used in

I am creating a Appbar with material UI. When I use a custom hook. to control the child component it also controls the whole parent component...
My purpose is to use this hook to disappear the component whenever a click is made outside of the component
Here is my custom hook
useListener.js
import { useEffect, useState, useRef } from "react";
export const useListener = (active, ref) => {
ref = useRef();
const [open, setOpen] = useState((active = false));
useEffect(() => {
function handleClickOutside(event) {
if (ref.current && !ref.current.contains(event.target)) {
setOpen(!open);
return;
}
}
// Bind the event listener
document.body.addEventListener("click", handleClickOutside);
return () => {
// Unbind the event listener on clean up
document.body.removeEventListener("click", handleClickOutside);
};
}, [open, ref]);
return [open, ref];
};
when I use it in the component by destructing it with
const [open, ref] = useListener()
and use it inside the component, I set open to appear and disappear the component, with CSS..
display: open ? 'block' : 'none'
Now when I use this component in which this hook is being used, When I click on this component it appears, and when I click outside of the component (any where else in the body) it disappears, which is totally fine...
But the issue is when I click on the parent component in with this component is being used it also makes appear this child component...
Here is my child component...
Profile.js
import React from "react";
import Paper from "#mui/material/Paper";
import Box from "#mui/material/Box";
import cover from "../assets/cover.webp";
import profilepic from "../assets/profilepic.webp";
import Button from "#mui/material/Button";
import Typography from "#mui/material/Typography";
import { LogoutIcon } from "../assets/LogoutIcon";
import { ChangePasswordIcon } from "../assets/ChangePasswordIcon";
import { useListener } from "../../../hooks/useListener";
const logout = () => {
localStorage.removeItem("authorization");
localStorage.removeItem("user");
localStorage.removeItem("permissions");
window.location.reload(false);
};
const Profile = () => {
const [open, profileRef] = useListener();
console.log(profileRef.current);
return (
<Box
ref={profileRef}
sx={{
display: open ? "inline" : "none",
width: "190px",
}}
>
<Paper elevation={2}>
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "center",
}}
>
<img src={cover} alt="Cover" style={{ width: "190px" }}></img>
<img
src={profilepic}
alt="Profile"
style={{ height: "62px", width: "62px", borderRadius: "50%" }}
></img>
<Typography variant="button" display="block" gutterBottom>
Username
</Typography>
<Button>
<Box sx={{ display: "flex", flexDirection: "row" }}>
<ChangePasswordIcon sx={{ height: "18px", width: "18px" }} />
<Typography variant="body1" gutterBottom>
Change password
</Typography>
</Box>
</Button>
<Button onClick={logout}>
<Box sx={{ display: "flex", flexDirection: "row" }}>
<LogoutIcon sx={{ width: "16px", height: "16px" }} />
<Typography variant="body1" gutterBottom>
Logout
</Typography>
</Box>
</Button>
</Box>
</Paper>
</Box>
);
};
export default Profile;
And this is the parent component...
TopbarContents.js
import React, { useState } from "react";
import Box from "#mui/material/Box";
import Button from "#mui/material/Button";
import Typography from "#mui/material/Typography";
import profilepic from "../assets/profilepic.webp";
import Profile from "./Profile";
export const TopbarContents = () => {
const [profileActive, toggleProfile] = useState(false);
const openProfile = () => {
toggleProfile(true);
};
return (
<Box sx={{ width: "100%" }}>
<Box
sx={{
width: "100%",
display: "flex",
alignItems: "center",
}}
>
<Box sx={{ flexGrow: 1 }}>
<Typography
sx={{ color: "#494343" }}
variant="h6"
noWrap
component="div"
>
Dashboard
</Typography>
</Box>
<Box
sx={{
height: "45px",
width: "160px",
borderRadius: 2,
display: "flex",
flexDirection: "column",
justifyContent: "center",
border: "1px solid #e0e0e0",
pl: "8px",
}}
>
<Typography sx={{ color: "#2E4299", pt: 1 }} variant="caption">
Case study
</Typography>
<Typography sx={{ color: "#494343" }} variant="overline">
Trial ID: NC48023194
</Typography>
</Box>
<Button
color="guava"
variant="contained"
size="medium"
sx={{ fontFamily: "Poppins", mr: 6, ml: 3 }}
>
Case Study
</Button>
<Button onClick={openProfile}>
<img
src={profilepic}
alt="Profile"
style={{ height: "62px", width: "62px", borderRadius: "50%" }}
></img>
</Button>
</Box>
<Box
sx={{
display: profileActive ? "inline" : "none",
flexDirection: "column",
}}
>
<Profile />
</Box>
</Box>
);
};

MUI Cards are not rendering with style

I am importing the Card component from MUI but the component does not have any style.
import * as React from "react";
import Box from "#mui/material/Box";
import Card from "#mui/material/Card";
import CardActions from "#mui/material/CardActions";
import CardContent from "#mui/material/CardContent";
import Button from "#mui/material/Button";
import Typography from "#mui/material/Typography";
const bull = (
<Box
component="span"
sx={{ display: "inline-block", mx: "2px", transform: "scale(0.8)" }}
>
•
</Box>
);
export default function BasicCard() {
return (
<Card sx={{ minWidth: 275 }}>
<CardContent>
<Typography sx={{ fontSize: 14 }} color="text.secondary" gutterBottom>
Word of the Day
</Typography>
<Typography variant="h5" component="div">
be{bull}nev{bull}o{bull}lent
</Typography>
<Typography sx={{ mb: 1.5 }} color="text.secondary">
adjective
</Typography>
<Typography variant="body2">
well meaning and kindly.
<br />
{'"a benevolent smile"'}
</Typography>
</CardContent>
<CardActions>
<Button size="small">Learn More</Button>
</CardActions>
</Card>
);
}
What the component is supposed to look like:
MUI Component
What the component actually looks like:
Imported Component
How can I add styling?
You probably have text-align: center set somewhere in the parent. This usually happens when you create a react project with a template like CRA that has some CSS files like this:
.App {
text-align: center;
}
You can fix it by finding and removing that text-align property or reset it in your Card:
<Card sx={{ minWidth: 275, textAlign: "initial" }}>
If what you mean is the dark background, you can achieve it by setting the theme mode to dark:
import { ThemeProvider, createTheme } from "#mui/material/styles";
const theme = createTheme({
palette: {
mode: "dark"
}
});
<ThemeProvider theme={theme}>
<Card sx={{ minWidth: 275 }}>
{...}
</Card>
</ThemeProvider>

Material Ui card change according to input

I have used material ui card and when i display it. It shows like below image. I want to show my card like that when cards do not fit the page it goes below and all card size must be same. How can i do that?
Here is my code:
const useStyles = makeStyles({ // Styling for my cards
root: {
width: 255,// i changed that line and below line but nothing happened
},
media: {
height: 190,
},
});
export default function AlbumsCard() {
const classes = useStyles();
..... //Some http requests
return (
<div>
<div>
<input
style={{
width: 500,
"margin-left": "auto",
"margin-right": "auto",
"margin-top": "10px",
}}
type="text"
placeholder="Search Album"
onChange={handleChange}
value={input}
/>
</div>
<div style={{ display: "flex" }}> //cardss
{k.map((album) => (
<Link
to={`/albums/${album.album_id}`}
style={{ textDecoration: "none", color: "#15cdfc" }}
>
<Card style={{ margin: "10px" }} className={classes.root}>
<CardActionArea>
<CardMedia
className={classes.media}
image={album.album_pfp}
title={album.album_name}
/>
<CardContent>
<Typography gutterBottom variant="h5" component="h2">
{album.album_name}
</Typography>
<Typography
variant="body2"
color="textSecondary"
component="p"
>
{album.album_song_count}
</Typography>
</CardContent>
</CardActionArea>
</Card>
</Link>
))}
</div>
</div>
);
}
Also the image from my app:
You can see that above. All cards placed in a line and some cards height's are different. Also there is a scroll bar.
I want to display whole card i a same size and when it overflows the page. It goes below.
Updated version:
Now each card has a different size how can i solve that? I think it is from image size.

Categories