Using axios to make use of a service not working - javascript

I'm trying to use S3 service to upload an image and it's telling me that certain variables aren't defined when I have defined them. I have imported axios and all the other stuff that are required
import React, { useState } from "react";
import ReactDOM from "react-dom";
import axios from "axios";
import Grid from "#material-ui/core/Grid";
import Button from "#material-ui/core/Button";
import Card from "#material-ui/core/Card";
import TextField from "#material-ui/core/TextField";
import CreateIcon from "#material-ui/icons/Create";
import Box from "#material-ui/core/Box";
import CardMedia from "#material-ui/core/CardMedia";
import MuiAlert from "#material-ui/lab/Alert";
import Snackbar from "#material-ui/core/Snackbar";
import { withStyles } from "#material-ui/core/styles";
import { makeStyles } from "#material-ui/core/styles";
import Chip from "#material-ui/core/Chip";
import Avatar from "#material-ui/core/Avatar";
import Slider from "#material-ui/core/Slider";
import Typography from "#material-ui/core/Typography";
import InputAdornment from "#material-ui/core/InputAdornment";
import { connect } from "react-redux";
function mapStateToProps(state) {
return {};
}
const useStyles = makeStyles((theme) => ({
root: {
"& > *": {
margin: theme.spacing(1),
marginLeft: theme.spacing(15),
},
},
input: {
display: "none",
},
}));
const useSliderStyles = makeStyles({
root: {
width: 250,
},
input: {
width: 100,
},
});
const UploadButton = () => {
const classes = useStyles();
return (
<div className={classes.root}>
<input
accept='image/*'
className={classes.input}
id='contained-button-file'
multiple
type='file'
/>
<label htmlFor='contained-button-file'>
<Button variant='contained' color='primary' component='span'>
Upload
</Button>
</label>
</div>
);
};
const StyledCard = withStyles({
root: { height: 600, width: 350 },
})(Card);
const PetitionForm = () => {
const [title, setTitle] = useState("");
const [description, setDescription] = useState("");
const [open, setOpen] = useState(false);
const [petition, validPetition] = useState(false);
const [noTitle, titleError] = useState(false);
const [noDescription, descriptionError] = useState(false);
const [hashtag, setHashtag] = useState("");
const [arrayOfHashtags, addHashtag] = useState([]);
const [money, setMoney] = React.useState(500);
const slider = useSliderStyles();
const handleTitleChange = (event) => setTitle(event.target.value);
const handleDescriptionChange = (event) => setDescription(event.target.value);
const handleClose = (event, reason) => {
if (reason === "clickaway") {
return;
}
};
const Alert = (props) => (
<MuiAlert elevation={6} variant='filled' {...props} />
);
const clearField = (event) => {
setOpen(true);
if (title.length > 0 && description.length > 0) {
validPetition(true);
setTitle("");
setDescription("");
addHashtag([]);
setHashtag("");
axios({
url: `call/s3/backend`,
method: "post",
data: {
images: imageArray.toByteArray(),
},
})
.then((res) => {
imageUrlArr = res.data;
axios({
url: `api/petition_posts`,
method: "post",
data: {
petition_post: {
title: title,
description: description,
hashtags: arrayOfHashtags.join(" "),
amount_donated: 0,
media: imageUrlArr,
goal: money,
card_type: "petition",
org_profile_id: 1,
},
},
})
.then((res) => {
console.log(res.data);
})
.catch((error) => console.log(error));
})
.catch((error) => console.log(error));
}
titleError(true ? title.length === 0 : false);
descriptionError(true ? description.length === 0 : false);
};
const handleDelete = (h) => () => {
addHashtag((arrayOfHashtags) =>
arrayOfHashtags.filter((hashtag) => hashtag !== h)
);
};
const handleHashtagChange = (event) => setHashtag(event.target.value);
const handleSliderChange = (event, newValue) => {
setMoney(newValue);
};
const handleInputChange = (event) => {
setMoney(event.target.value === "" ? "" : Number(event.target.value));
};
const newHashtag = () => {
if (arrayOfHashtags.length < 3) {
addHashtag((arrayOfHashtags) => arrayOfHashtags.concat(hashtag));
} else {
console.log("Too many hashtags");
}
};
const Hashtags = arrayOfHashtags.map((h) => (
<Chip
key={h.length}
size='small'
avatar={<Avatar>#</Avatar>}
label={h}
onDelete={handleDelete(h)}
/>
));
return (
<StyledCard>
<Box mt={1}>
<Grid container justify='center'>
<TextField
id='outlined-multiline-static'
multiline
rows={1}
variant='outlined'
placeholder='Title'
value={title}
onChange={handleTitleChange}
helperText={
open // only displays helper text if button has been clicked and fields haven't been filled
? !noTitle || petition
? ""
: "Can't be an empty field"
: ""
}
/>
</Grid>
</Box>
<Box mt={1}>
<Grid container justify='center'>
<CardMedia title='Petition'>
<UploadButton />
</CardMedia>
</Grid>
</Box>
<div className={slider.root}>
<Typography>Amount to raise</Typography>
<Box>
<Grid container justify='center'>
<Slider
min={500}
max={10000}
value={typeof money === "number" ? money : 0}
onChange={handleSliderChange}
aria-labelledby='input-slider'
/>
<TextField
className={slider.input}
value={money}
onChange={handleInputChange}
InputProps={{
startAdornment: (
<InputAdornment position='start'>$</InputAdornment>
),
}}
helperText={
money < 500 || money > 10000
? "Please enter a value between 500 and 10000"
: ""
}
/>
</Grid>
</Box>
</div>
<Box mt={1} mb={1}>
<Grid container justify='center'>
<TextField
size='small'
inputProps={{
style: { fontSize: 15 },
}}
id='outlined-multiline-static'
multiline
rows={1}
placeholder='Hashtags'
variant='outlined'
value={hashtag}
onChange={handleHashtagChange}
helperText={
arrayOfHashtags.length === 3
? "You reached the maximum amount of hashtags"
: ""
}
/>
<Button color='primary' onClick={newHashtag}>
Create!
</Button>
{arrayOfHashtags.length > 0 ? Hashtags : ""}
</Grid>
</Box>
<Box mt={1} justify='center'>
<Grid container justify='center'>
<TextField
size='small'
inputProps={{
style: { fontSize: 15 },
}}
id='outlined-multiline-static'
multiline
rows={5}
placeholder='Description'
variant='outlined'
value={description}
onChange={handleDescriptionChange}
helperText={
// only displays helper text if button has been clicked and fields haven't been filled
open
? !noDescription || petition
? ""
: "Can't be an empty field"
: ""
}
/>
</Grid>
</Box>
<Box mt={1}>
<Grid container justify='center'>
<Button onClick={clearField}>
<CreateIcon />
Create Petition!
</Button>
{open && petition && (
<Snackbar open={open} autoHideDuration={2000} onClose={handleClose}>
<Alert severity='success'>
You have successfully create a petition!
</Alert>
</Snackbar>
)}
{open && !petition && (
<Snackbar open={open} autoHideDuration={2000} onClose={handleClose}>
<Alert severity='error'>You're missing one or more fields</Alert>
</Snackbar>
)}
</Grid>
</Box>
</StyledCard>
);
};
export default connect(mapStateToProps)(PetitionForm);
This is the error I'm getting, someone mentioned something about the scope and I think that shouldn't matter when I'm trying to assign a value to a variable as far I as know
Line 109:19: 'imageArray' is not defined no-undef
Line 113:11: 'imageUrlArr' is not defined no-undef
Line 123:24: 'imageUrlArr' is not defined no-undef
Search for the keywords to learn more about each error.

Related

Getting the error " React has detected a change in the order of Hooks called by StudentsFilter"

//StudentsFilter.jsx
import {
Accordion,
AccordionButton,
AccordionIcon,
AccordionItem,
AccordionPanel,
Badge,
Box,
Button,
Checkbox,
Flex,
Radio,
RadioGroup,
Text,
useColorMode,
useColorModeValue,
VStack,
} from "#chakra-ui/react";
import React, { useState } from "react";
import { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { axiosInstance } from "../../../axiosConfig";
import { commonSlidercss, darkSlidercss } from "../../../GlobalStyles";
import {
setFilterSearchMode,
setSearchingBatch,
setSearchingStream,
} from "../../../redux/slices/adminUserSlice";
const StudentsFilter = () => {
const [streams, setStreams] = useState(null);
const [batchYear, setBatchYear] = useState([]);
const [checkedStreams, setCheckedStreams] = useState([]);
const [checkedBatches, setCheckedBatches] = useState([]);
const siteState = useSelector((state) => state.siteReducer);
const adminUsers = useSelector((state) => state.adminUserReducer);
const filterSearchMode = adminUsers?.filterSearchMode;
const site = siteState.siteInfo;
const { colorMode } = useColorMode();
const dispatch = useDispatch();
useEffect(() => {
getStream();
let batches = [];
if (site) {
let year = site.year_established;
let current_year = new Date().getFullYear();
let year_diff = current_year - site.year_established;
for (let i = 0; i <= year_diff; i++) {
batches.push(year + i);
}
setBatchYear(batches);
}
}, [site]);
const getStream = async () => {
try {
const res = await axiosInstance.get("stream");
setStreams(res?.data?.stream);
} catch (error) {
console.log("Something went wrong while getting streams", e);
}
};
const streamsHandler = (e, li) => {
e.stopPropagation();
const index = checkedStreams.indexOf(li);
if (index > -1) {
setCheckedStreams([
...checkedStreams.slice(0, index),
...checkedStreams.slice(index + 1),
]);
} else {
setCheckedStreams([...checkedStreams, li]);
}
};
const batchesHandler = (e, li) => {
e.stopPropagation();
const index = checkedBatches.indexOf(li);
if (index > -1) {
setCheckedBatches([
...checkedBatches.slice(0, index),
...checkedBatches.slice(index + 1),
]);
} else {
setCheckedBatches([...checkedBatches, li]);
}
};
useEffect(() => {
dispatch(setSearchingStream(checkedStreams));
dispatch(setSearchingBatch(checkedBatches));
}, [checkedBatches, checkedStreams]);
return (
<Flex
p="6"
direction="column"
style={{ height: "inherit" }}
align="space-between"
justify="space-between"
w="300px"
maxH={231}
overflowY="scroll"
css={colorMode === "light" ? commonSlidercss : darkSlidercss}
>
<Box>
<Text fontWeight="medium" fontSize="sm" mb={7}>
More filters
</Text>
<Accordion allowMultiple>
<AccordionItem>
<AccordionButton>
<Box flex="1" fontSize="xs" textAlign="left">
Batch
</Box>
<AccordionIcon />
</AccordionButton>
<AccordionPanel pb={4}>
<RadioGroup>
<VStack align="start">
{batchYear &&
batchYear.map((li) => (
<Checkbox
// onChange={checkboxChange}
key={li}
value={li}
colorScheme={useColorModeValue(
"primaryScheme",
"purple"
)}
size="sm"
onChange={(e) => batchesHandler(e, li)}
isChecked={checkedBatches.includes(li)}
>
<Text fontSize="xs">{li}</Text>
</Checkbox>
))}
</VStack>
</RadioGroup>
</AccordionPanel>
</AccordionItem>
<AccordionItem>
<AccordionButton>
<Box flex="1" textAlign="left" fontSize="xs">
Stream
</Box>
<AccordionIcon />
</AccordionButton>
<AccordionPanel pb={4}>
<RadioGroup>
<VStack align="start">
{streams &&
streams.map((li) => (
<Checkbox
// onChange={checkboxChange}
key={li.id}
value={li.id}
colorScheme={useColorModeValue(
"primaryScheme",
"purple"
)}
size="sm"
onChange={(e) => streamsHandler(e, li.id)}
isChecked={checkedStreams.includes(li.id)}
>
<Text fontSize="xs">{li?.name}</Text>
</Checkbox>
))}
</VStack>
</RadioGroup>
</AccordionPanel>
</AccordionItem>
</Accordion>
</Box>
<Box>
<Button
width="full"
h="40px"
borderRadius="10px"
fontWeight="500"
variant="primary"
mt="10px"
onClick={() => dispatch(setFilterSearchMode(!filterSearchMode))}
>
Filter
</Button>
</Box>
</Flex>
);
};
export default StudentsFilter;
What is the reason why I am getting the error " React has detected a change in the order of Hooks called by StudentsFilter. This will lead to bugs and errors if not fixed" I have seen this warning in 2-3 components and also tried to correct it but I don't know what I am doing wrong? Can someone help me to identify it?
You're calling the useColorModeValue conditionally (and in a loop) in the return statement. That's probably the source of the error.
You should use ESLint and the "rules of hooks" rule, it would have been highlighted directly in your editor.

Redux Toolkit Query not fetching data

I am trying to fetch data with RTK Query in next.js project and everything were fine until I had to fetch some more data from /api/exams endpoint. I have fetched almost everything from that endpoint and i know that's working fine but i still can't fetch some data from it. I'll provide screenshots of all code that's related to it. ok so here is the code where endpoints are:
Then let's continue with exams-response where i define body of endpoint:
Now I will provide code in my custom hook where i import that data from api/exams endpoint query:
And now i will show code of the actual page where i use them and where i think problem may lie also with another file which i will provide after this:
import { memo } from "react"
import { useIntl } from "react-intl"
import Stack from "#mui/material/Stack"
import Typography from "#mui/material/Typography"
import { ExamoTypesEnum } from "src/common/types/examo-types-enum"
import { rolesEnum } from "src/core/roles-enum"
import { useExamAssign } from "src/features/exams/hooks/use-exam-assign"
import { useExams } from "src/features/exams/hooks/use-exams"
import { useStartExam } from "src/features/exams/hooks/use-start-exam"
import { useIsMobile } from "src/helpers/use-is-mobile"
import { useAppSelector } from "src/redux/hooks"
import { ExamoCard } from "src/ui/examo/examo-card"
import { ExamoCardsGrid } from "src/ui/examo/examo-cards-grid"
import { ExamoHeader } from "src/ui/examo/examo-header"
import { CustomizedDialogs } from "src/ui/filter"
import { LoadingSpinner } from "src/ui/loading-spinner"
import { styled } from "src/ui/theme"
import { UnauthenticatedComponent } from "src/ui/unauthenticated"
import { useTags } from "../tags/hooks/use-tags"
import { useActiveExamQuery } from "./api"
const Ourbox = styled.div`
display: flex;
justify-content: space-between;
`
export const ExamsPage = memo(() => {
const isMobile = useIsMobile()
const userRole = useAppSelector((state) => state.auth.role)
const intl = useIntl()
const {
exams,
isLoadingExams,
selectedTags,
setSelectedTags,
checkedFilterTags,
setCheckedFilterTags,
} = useExams()
const { availableTags } = useTags()
const isLoadingAnExam = useAppSelector((state) => state.exam.isLoadingAnExam)
const { startAsync } = useStartExam()
const { data: activeExam, isFetching: isFetchingActiveExam } =
useActiveExamQuery(undefined, { refetchOnMountOrArgChange: 1 })
if (userRole === rolesEnum.None) {
return <UnauthenticatedComponent />
}
return (
<Stack sx={{ paddingX: isMobile ? 3 : "10vw", paddingY: 4 }} gap={4}>
<Ourbox>
<ExamoHeader
header={intl.formatMessage({
id: "exams-header",
defaultMessage: "Choose your exam",
})}
subtitle={intl.formatMessage({
id: "exams-header-subtitle",
defaultMessage:
"Our operators make quizzes and tests to help you upgrade and test your skills.",
})}
/>
<CustomizedDialogs
id="exams-page-filter"
selectedTags={selectedTags}
setSelectedTags={setSelectedTags}
availableTags={availableTags || []}
checkedFilterTags={checkedFilterTags}
setCheckedFilterTags={setCheckedFilterTags}
/>
</Ourbox>
{isLoadingExams && <LoadingSpinner />}
{!isLoadingExams && (!exams || exams.length === 0) && (
<Typography>
{intl.formatMessage({
id: "no-exams-available",
defaultMessage: "No exams available",
})}
</Typography>
)}
{exams && exams.length > 0 && (
<ExamoCardsGrid>
{exams.map((exam) => (
<ExamoCard
key={exam.id}
type={ExamoTypesEnum.EXAM}
useAssign={useExamAssign}
isStartButtonDisabled={
isLoadingAnExam ||
isFetchingActiveExam ||
(activeExam?.exam?.id !== undefined &&
exam.id !== activeExam.exam.id)
}
isResuming={
activeExam?.exam?.id !== undefined &&
exam.id === activeExam.exam.id
}
handleStart={() => startAsync(exam.id)}
isLoading={isLoadingAnExam}
title={exam.title}
duration={exam.duration}
tags={[
...new Set(exam.templates?.flatMap((et) => et.tags) || []),
]}
numberOfQuestions={exam.templates.reduce(
(total, current) => total + current.numberOfQuestions,
0,
)}
deadline-start={exam["deadline-start"]}
deadline-end={exam["deadline-end"]}
i={exam.id}
/>
))}
</ExamoCardsGrid>
)}
</Stack>
)
})
and the last one which is as mapped through in above the code. so it's :
import { memo } from "react"
import * as React from "react"
import { useIntl } from "react-intl"
import AccessTimeIcon from "#mui/icons-material/AccessTime"
import ExpandMoreIcon from "#mui/icons-material/ExpandMore"
import MoreHorizIcon from "#mui/icons-material/MoreHoriz"
import Box from "#mui/material/Box"
import Card from "#mui/material/Card"
import MuiChip from "#mui/material/Chip"
import Collapse from "#mui/material/Collapse"
import Grid from "#mui/material/Grid"
import IconButton, { IconButtonProps } from "#mui/material/IconButton"
import Stack from "#mui/material/Stack"
import { styled } from "#mui/material/styles"
import Typography from "#mui/material/Typography"
import { ExamoTypesEnum } from "src/common/types/examo-types-enum"
import { useAssignType } from "src/common/types/use-assign-type"
import { useAppSelector } from "src/redux/hooks"
import { ExamoAssignTo } from "src/ui/examo/examo-assign-to"
import { ExamoStartDialogBtn } from "src/ui/examo/examo-start-btn"
interface props {
duration: string | null
title: string
tags: string[] | null
numberOfQuestions: number | null
isLoading: boolean
handleStart: () => void
useAssign: useAssignType
isStartButtonDisabled: boolean
isResuming: boolean
type: ExamoTypesEnum
i: number
"deadline-start": string
"deadline-end": string
}
export const ExamoCard = memo(
({
duration,
tags,
title,
isLoading,
numberOfQuestions,
isStartButtonDisabled,
isResuming,
type,
handleStart,
useAssign,
i,
"deadline-end": deadlineEnd,
"deadline-start": deadlineStart,
}: props) => {
console.log(deadlineStart)
const intl = useIntl()
const user = useAppSelector((state) => state.auth)
const durationHours = duration?.split(":")[0]
const durationMinutes = duration?.split(":")[1]
// const [expanded, setExpanded] = React.useState(false)
const [expandedId, setExpandedId] = React.useState(-1)
// const handleExpandClick = () => {
// setExpanded(!expanded)
// }
const handleExpandClick = (i: number) => {
setExpandedId(expandedId === i ? -1 : i)
}
const preventParentOnClick = (event: React.MouseEvent<HTMLElement>) => {
event.stopPropagation()
}
interface ExpandMoreProps extends IconButtonProps {
expand: boolean
}
const ExpandMore = styled((props: ExpandMoreProps) => {
const { expand, ...other } = props
return <IconButton {...other} />
})(({ theme, expand }) => ({
transform: !expand ? "rotate(0deg)" : "rotate(180deg)",
transition: theme.transitions.create("transform", {
duration: theme.transitions.duration.shortest,
}),
}))
return (
<Grid item xs={12} lg={6}>
<Card
onClick={() => handleExpandClick(i)}
aria-expanded={expandedId === i}
elevation={2}
sx={{
padding: "1rem",
height: "100%",
borderRadius: "1rem",
border: "solid 1px var(--palette-grey-400)",
transition: "all 0.1s ease-in-out",
":hover": {
backgroundColor: "var(--palette-grey-100)",
cursor: "pointer",
},
}}
>
<Stack direction="row" justifyContent="space-between">
<Stack
gap={numberOfQuestions ? 1.5 : 6}
sx={{
width: "100%",
}}
>
<Stack
direction="row"
sx={{
justifyContent: "space-between",
}}
>
<Typography
variant="h5"
sx={{ whiteSpace: "pre-wrap", wordBreak: "break-all" }}
>
{title}
</Typography>
<ExpandMore expand={expandedId === i}>
<ExpandMoreIcon />
</ExpandMore>
<Stack
direction="row"
gap={1}
sx={{
justifyContent: "flex-end",
alignItems: "center",
marginTop: "-1.75rem",
}}
>
<AccessTimeIcon />
<Typography
whiteSpace="nowrap"
variant="h6"
>{`${durationHours}h ${durationMinutes}m`}</Typography>
</Stack>
</Stack>
<Collapse in={expandedId === i} timeout="auto" unmountOnExit>
<Stack direction="row" gap={4}>
{numberOfQuestions && (
<Typography variant="h6">
{`${numberOfQuestions} ${intl.formatMessage({
id: "questions",
defaultMessage: "Questions",
})}`}
</Typography>
)}
</Stack>
<Stack
direction="row"
sx={{ flexWrap: "wrap", gap: 1, marginTop: "1rem" }}
>
{tags?.map((t, index) => (
<MuiChip
key={index}
label={t}
variant="filled"
sx={{ fontWeight: "bold" }}
color="secondary"
size="small"
/>
))}
</Stack>
</Collapse>
</Stack>
<Stack
sx={{ marginTop: "-0.5rem" }}
justifyContent="space-between"
alignItems="center"
spacing={user.role === "Operator" ? 0.1 : 1}
>
<MoreHorizIcon sx={{ marginLeft: "2rem" }} />
<Box onClick={preventParentOnClick}>
<Stack sx={{ marginLeft: "1.5rem" }}>
{user.role === "Operator" && (
<ExamoAssignTo useAssign={useAssign} title={title} />
)}
</Stack>
</Box>
<Box onClick={preventParentOnClick}>
<ExamoStartDialogBtn
type={type}
isResuming={isResuming}
handleStart={handleStart}
isLoading={isLoading}
isDisabled={isStartButtonDisabled}
/>
</Box>
</Stack>
</Stack>
</Card>
</Grid>
)
},
)
To sum up guys, I want to also fetch deadlineStart and deadlineEnd but i can't. I think problem is in last file or second to last, because maybe am not defining them properly in interface props in last code. And also i almost forgot to mention that when I try to console.log(deadlineStart) in the last code it says undefined in the browser. Edited Network Pic :
here is screenshot when i console log single exams :

Uncaught TypeError: setStatusFilters is not a function in react

So In my react application I have filtered option dialog. When a user select filter option and there is no related data, the dialog prompts No objects found based on your filter, try changing filter criteria and below this text I have a button called back to reset the filters. To do so I have defined a function resetAllFilters inside this function I called setStatusFilters.
But when I call resetAllFilters function I got Uncaught TypeError: setStatusFilters is not a function at resetAllFilters
Here is my code.
import { Search } from "#mui/icons-material";
import { Divider, Grid, List, Stack, Typography } from "#mui/material";
import React, { useEffect, useState, useMemo } from "react";
import TextInput from "../../../components/input/TextInput";
import Loading from "../../../components/loading/Loading";
import { filterObjects, filterSearch } from "../../../data/helpers/Helpers";
import TrackingFilterContainer from "../containers/TrackingFilterContainer";
import ObjectListItem from "./ObjectListItem";
import {
makeDefaultFilterState,
makeFilterOptionsObj,
} from "../../../data/helpers/Helpers";
import Button from "../../../components/button/Button";
const classes = {
Root: {
height: "100vh",
},
SearchInput: (theme) => ({
mt: "5%",
// ml: "5%",
p: 0.7,
borderRadius: "5px",
width: "100%",
bgcolor: "white",
"& input": {
overflow: "hidden",
textOverflow: "ellipsis",
},
"& svg": {
mr: "2.5%",
},
[theme.breakpoints.down("md")]: {
mt: 0,
pl: 1.5,
bgcolor: "background.primary",
},
}),
SearchLogo: { color: "misc.hint" },
Divider: (theme) => ({
mt: "2.5%",
width: "100%",
mb: 3,
[theme.breakpoints.down("md")]: {
display: "none",
},
}),
FilterWrapper: {
// mt: "3%",
px: "2%",
pt: "5%",
pb: "3%",
columnGap: "3%",
},
ListWrapper: {
// mt: "1.5%",
height: "100%",
overflow: "auto",
"&::-webkit-scrollbar": {
width: "3px",
},
"&::-webkit-scrollbar-thumb": {
borderRadius: "8px",
backgroundColor: "misc.hint",
},
},
};
function ObjectList({
search,
setSearch,
trackingObjects,
loading,
error,
selectedObj,
setSelectedObj,
statusFilters,
setStatusCheckboxFilters,
setStatusFilters,
}) {
const handleClick = React.useCallback((obj) => {
setSelectedObj(obj);
}, []);
console.log(statusFilters, "object");
const resultObjs = filterSearch(
filterObjects(trackingObjects, statusFilters),
search
);
const [res, setReset] = useState(false);
const reset = () => setReset(!setStatusFilters);
const objsWithLocations = resultObjs.filter(
({ location }) =>
location?.[0] !== null &&
location?.[0] !== undefined &&
location?.[1] !== null &&
location?.[1] !== undefined
);
const defaultFilterState = useMemo(
() => makeDefaultFilterState(trackingObjects),
[trackingObjects]
);
const filterOptionsObj = useMemo(
() => makeFilterOptionsObj(trackingObjects),
[trackingObjects]
);
const resetAllFilters = () => {
setStatusFilters([]);
};
// console.log('objsWithLocations', objsWithLocations);
return (
<Grid container direction="column" sx={classes.Root} wrap="nowrap">
<Stack
sx={{
flexDirection: { xs: "row", md: "column" },
alignItems: { xs: "center", md: "flex-start" },
justifyContent: { xs: "space-between", md: "flex-start" },
px: 1.0,
mb: 2,
}}
>
<TextInput
autoComplete="off"
variant="standard"
placeholder="Search for an object...."
value={search}
onValueChange={setSearch}
InputProps={{
startAdornment: <Search sx={classes.SearchLogo} />,
disableUnderline: true,
}}
sx={classes.SearchInput}
/>
<Divider sx={classes.Divider} />
<TrackingFilterContainer
defaultFilterState={defaultFilterState}
filterOptionsObj={filterOptionsObj}
/>
</Stack>
{loading && !resultObjs?.length && <Loading />}
{error && (
<Typography
variant="h5"
color="text.secondary"
mx="auto"
mt="5%"
width="45%"
textAlign="center"
>
{error}
</Typography>
)}
{!loading && objsWithLocations?.length === 0 ? (
<Typography
variant="h5"
color="text.secondary"
mx="auto"
mt="5%"
width="45%"
textAlign="center"
// onClick={() => defaultFilterState()}
>
No objects found based on your filter, try changing filter criteria
<Button
variant="text"
text="Back"
sx={{
fontSize: "24px",
p: 0,
verticalAlign: "baseline",
ml: "6px",
textTransform: "none",
}}
onClick={() => resetAllFilters()}
/>
</Typography>
) : (
<List sx={classes.ListWrapper}>
{objsWithLocations.map((obj) => (
<ObjectListItem
key={obj.trackingObjectId}
object={obj}
handleClick={handleClick}
isActive={selectedObj?.trackingObjectId === obj.trackingObjectId}
/>
))}
</List>
)}
</Grid>
);
}
export default ObjectList;
// export default React.memo(ObjectList);
Here is ObjectList.js rendered
import {Grid} from "#mui/material";
import {useNavigate} from "react-router-dom";
import {useTheme} from "#mui/material/styles";
import useMediaQuery from "#mui/material/useMediaQuery";
import React, {useEffect, useState} from "react";
import {TrackingPageItems} from "../../data/constants/TrackingObject";
import Map from "./map/Map";
import MobileNavigate from "./mobileNavigate/MobileNavigate";
import ObjectList from "./objectList/ObjectList";
import ObjectOne from "./objectOne/ObjectOne";
import buildSocketIoConnection from "../../data/socket.io/client";
import API from "../../data/api/API";
import {handleError} from "../../data/helpers/apiHelpers";
import {checkAuthStatus} from "../../data/helpers/Helpers";
import {filterObjects, filterSearch} from "../../data/helpers/Helpers";
function TrackingPage({
trackingObjects,
updateTrackingObjects,
setTrackingObjects,
selectedObject,
setSelectedObject,
...props
}) {
const [objectListSearch, setObjectListSearch] = useState("");
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down("md"));
const [selectedTab, setSelectedTab] = useState(TrackingPageItems.LIST);
const [loading, setLoading] = useState(true);
const [error, setError] = useState("");
const navigate = useNavigate();
const handleTabChange = (newTab) => {
setSelectedTab(newTab);
};
useEffect(() => {
const userInfoString = localStorage.getItem("userInfo");
const userInfo = JSON.parse(userInfoString);
const token = userInfo?.token;
let possibleSocketIoConnection = null;
if (token) {
possibleSocketIoConnection = buildSocketIoConnection(token, updateTrackingObjects);
} else {
console.error("No token provided. Won't connect to socket.io server");
}
return () => {
setSelectedObject(null);
possibleSocketIoConnection?.closeConnection?.();
};
}, []);
const fetchObjectList = React.useCallback((firstTime = false) => {
firstTime && setLoading(true);
API.object
.getObjectList()
.then((objs) => {
// console.log('TrackingObjects', objs.data);
setTrackingObjects(objs.data);
})
.catch((err) => {
console.log(err);
checkAuthStatus(err.response?.status, navigate);
setError(handleError(err, "getObjectList"));
})
.finally(() => {
firstTime && setLoading(false)
});
}, []);
useEffect(() => {
fetchObjectList(!trackingObjects?.length);
// const interval = setInterval(fetchObjectList, 20000);
// return () => clearInterval(interval);
}, []);
const resultObjs = filterSearch(filterObjects(trackingObjects, props.statusFilters), objectListSearch);
return (
<>
<MobileNavigate selectedTab={selectedTab} handleTabChange={handleTabChange} />
<Grid container direction="row" spacing={1}>
{(!isMobile || (isMobile && selectedTab === TrackingPageItems.LIST)) && (
<Grid item container direction="column" xs={12} md={3}>
{selectedObject ? (
<ObjectOne trackingObjects={trackingObjects} selectedObj={selectedObject} setSelectedObj={setSelectedObject} />
) : (
<ObjectList
search={objectListSearch}
setSearch={setObjectListSearch}
selectedObj={selectedObject}
setSelectedObj={setSelectedObject}
trackingObjects={trackingObjects}
loading={loading}
error={error}
{...props}
/>
)}
</Grid>
)}
{(!isMobile || (isMobile && selectedTab === TrackingPageItems.MAP)) && (
<Grid item container direction="column" xs={12} md={9}>
<Map
loading={loading}
selectedObj={selectedObject}
setSelectedObj={setSelectedObject}
trackingObjects={resultObjs}
{...props}
/>
</Grid>
)}
</Grid>
</>
);
}
export default React.memo(TrackingPage);
How can I solve this error?

How can I pass values or fields from one page to another page in ReactJS?

How can I send the value of the checkbox to the checkout.js page? This is the PaymentForm page. I tried my best but it's not working correctly. Basically, I want to use the PaymentForm fields in checkout.js page because my submit button is there.
PaymentForm.js
import React from 'react';
import Typography from '#material-ui/core/Typography';
import Grid from '#material-ui/core/Grid';
import TextField from '#material-ui/core/TextField';
import FormControlLabel from '#material-ui/core/FormControlLabel';
import Checkbox from '#material-ui/core/Checkbox';
import { createStyles } from '#material-ui/core/styles';
import StripeCheckout from 'react-stripe-checkout'
import 'react-toastify/dist/ReactToastify.css';
const styles = createStyles({
formControlLabel: {
fontSize: '1.5rem',
'& label': { fontSize: '5rem' }
}
});
const handleToken = (token) => {
console.log(token);
}
const PaymentForm = ({ PaymentForm, changePaymentForm }) => {
const [state, setState] = React.useState({
checkedA: false,
});
const handleChange = (event) => {
setState({ ...state, [event.target.name]: event.target.checked });
};
return (
<React.Fragment>
<Typography variant="h4" gutterBottom>
Payment method
</Typography><br />
<Grid container spacing={3}>
<Grid item xs={12}>
<FormControlLabel
control={<Checkbox checked={state.checkedA} onChange={handleChange} name="checkedA"/>}
label={<Typography style={styles.formControlLabel}>Cash on delivery</Typography>}
/>
</Grid>
<Grid item xs={12}>
<StripeCheckout
stripeKey="pk_test_51I9XPQAesAg2GfzQyVB7VgP0IbmWwgcfeFJSuCpB2kbNu60AFTbFhC7dxwje8YF4w2ILMJ6o2InB9ENczpd4dCSa00e09XoDbw"
token={handleToken}
amount={2 * 100}
name="All Products"
/>
</Grid>
</Grid>
</React.Fragment>
);
};
export default PaymentForm;
Checkout.js
import React from 'react';
import { makeStyles } from '#material-ui/core/styles';
import CssBaseline from '#material-ui/core/CssBaseline';
import AppBar from '#material-ui/core/AppBar';
import Toolbar from '#material-ui/core/Toolbar';
import Paper from '#material-ui/core/Paper';
import Stepper from '#material-ui/core/Stepper';
import Step from '#material-ui/core/Step';
import StepLabel from '#material-ui/core/StepLabel';
import Button from '#material-ui/core/Button';
import Link from '#material-ui/core/Link';
import Typography from '#material-ui/core/Typography';
import axios from '../../axios-orders';
import AddressForm from './CheckoutForm';
import PaymentForm from './PaymentForm';
import Review from './Review';
const useStyles = makeStyles((theme) => ({
appBar: {
position: 'relative',
},
layout: {
width: 'auto',
marginLeft: theme.spacing(2),
marginRight: theme.spacing(2),
[theme.breakpoints.up(1000 + theme.spacing(2) * 2)]: {
width: 1100,
marginLeft: 'auto',
marginRight: 'auto',
},
},
paper: {
marginTop: theme.spacing(3),
marginBottom: theme.spacing(3),
padding: theme.spacing(2),
[theme.breakpoints.up(700 + theme.spacing(3) * 2)]: {
marginTop: theme.spacing(6),
marginBottom: theme.spacing(6),
padding: theme.spacing(3),
backgroundColor: 'rgb(248, 246, 244)',
},
},
stepper: {
padding: theme.spacing(5, 0, 5),
fontWeight: 'bold',
backgroundColor: 'rgb(248, 246, 244)',
},
buttons: {
display: 'flex',
justifyContent: 'flex-end',
},
button: {
marginTop: theme.spacing(3),
marginLeft: theme.spacing(1),
border: "none"
},
}));
const steps = ['Shipping address', 'Payment details', 'Review your order'];
function Copyright() {
return (
<Typography variant="body2" color="textSecondary" align="center">
{'Copyright © '}
<Link color="inherit" href="https://material-ui.com/">
Your Website
</Link>{' '}
{new Date().getFullYear()}
{'.'}
</Typography>
);
}
function getStepContent(step, formValues = null, changeFormValue = null, paymentValues = null, changePaymentValue = null) {
switch (step) {
case 0:
return <AddressForm addressValues={formValues} changeAddressValue={changeFormValue} />;
case 1:
return <PaymentForm PaymentForm={paymentValues} changePaymentForm={changePaymentValue}/>;
case 2:
return <Review />;
default:
throw new Error('Unknown step');
}
}
export default function Checkout(props) {
const classes = useStyles();
const [addressFormValues, setAddressFormValues] = React.useState({});
const [paymentFormValues, setPaymentFormValues] = React.useState({});
const [paymentFormNewValues, setPaymentFormNewValues] = React.useState({});
const [activeStep, setActiveStep] = React.useState(0);
if(paymentFormValues === true){
setPaymentFormNewValues('Cash')
}
if(paymentFormValues === false){
setPaymentFormNewValues('Online')
}
console.log('[paymentFormNewValues: ]', paymentFormNewValues)
console.log('[paymentFormValues: ]', paymentFormValues)
const handleNext = () => {
setActiveStep(activeStep + 1);
axios.post('/UserPortal/CartItems/checkout_details_check.php', {
customer_id: localStorage.getItem('Id'),
})
.then((response) => {
if(response.data === null)
{
axios.post('/UserPortal/CartItems/checkout_details.php', {
customer_id: localStorage.getItem('Id'),
firstname: addressFormValues.firstname,
lastname: addressFormValues.lastname,
address: addressFormValues.address,
city: addressFormValues.city,
state: addressFormValues.state
})
.then((response) => {
console.log(response.data);
})
}
else{
axios.post('/UserPortal/CartItems/checkout_details_update.php', {
customer_id: localStorage.getItem('Id'),
firstname: addressFormValues.firstname,
lastname: addressFormValues.lastname,
address: addressFormValues.address,
city: addressFormValues.city,
state: addressFormValues.state,
payment_method: paymentFormNewValues
})
.then((response) => {
console.log(response.data);
})
}
})
};
const handleBack = () => {
setActiveStep(activeStep - 1);
};
const changeAddressFormValue = (key, value) => {
let values = { ...addressFormValues };
values[key] = value;
setAddressFormValues(values);
};
const changePaymentFormValue = (key, value) => {
let values = { ...addressFormValues };
values[key] = value;
setPaymentFormValues(values);
};
return (
<React.Fragment>
<CssBaseline />
<AppBar position="absolute" color="default" className={classes.appBar}></AppBar>
<main className={classes.layout}>
<Paper className={classes.paper}>
<Typography component="h1" variant="h3" align="center">
Checkout
</Typography>
<Stepper activeStep={activeStep} className={classes.stepper}>
{steps.map((label) => (
<Step key={label}>
<StepLabel><Typography component="h1" variant="h5" align="center">
{label} </Typography></StepLabel>
</Step>
))}
</Stepper>
<React.Fragment>
{activeStep === steps.length ? (
<React.Fragment>
<Typography variant="h5" gutterBottom>
Thank you for your order.
</Typography>
<Typography variant="subtitle1">
Your order number is #2001539. We have emailed your order
confirmation, and will
send you an update when your order has shipped.
</Typography>
</React.Fragment>
) : (
<React.Fragment>
{activeStep === 0 ? getStepContent(activeStep, addressFormValues, changeAddressFormValue , paymentFormValues, changePaymentFormValue) : getStepContent(activeStep)}
{ <div className={classes.buttons}>
{ activeStep !== 0 && (
<Button variant="contained" style={{outline: 'none'}}
className={classes.button}
onClick={handleBack}
>
Back
</Button>
)}
<Button style={{outline: 'none'}}
variant="contained"
color="secondary"
onClick={handleNext}
className={classes.button}
>
{activeStep === steps.length - 1 ? 'Place order' : 'Next'}
</Button>
</div> }
</React.Fragment>
)}
</React.Fragment>
</Paper>
<Copyright />
</main>
</React.Fragment>
);
}
It seems you have checked the activeStep wrong.
Maybe the right code must be like the following:
<React.Fragment>
{activeStep !== 0 ?getStepContent(activeStep, addressFormValues, changeAddressFormValue , paymentFormValues, changePaymentFormValue) : getStepContent(activeStep)}
Do you ever consider using Context API?
React Context API
But also you can use create a checkboxValue with useState in Checkout.js and pass setCheckBoxValue to PaymentForm in getStepContent as prop. When checkbox checked trigger setCheckBoxValue and it will trigger parent component's state (Checkbox).

Styling a card causes TextField to lose focus in Material UI + React

I'm trying to style my card so that it's not so big but the problem is every time I do that, my TextField loses its' functionality and I have to keep on clicking on the TextField because it keeps on losing focus. I need to make my Card component smaller without losing the functionality of my TextField.
https://codesandbox.io/s/mutable-monad-dsvf8?file=/src/index.js
import React, { useState } from "react";
import ReactDOM from "react-dom";
import Grid from "#material-ui/core/Grid";
import Button from "#material-ui/core/Button";
import Card from "#material-ui/core/Card";
import TextField from "#material-ui/core/TextField";
import CreateIcon from "#material-ui/icons/Create";
import Box from "#material-ui/core/Box";
import CardMedia from "#material-ui/core/CardMedia";
import MuiAlert from "#material-ui/lab/Alert";
import Snackbar from "#material-ui/core/Snackbar";
import { withStyles } from "#material-ui/core/styles";
const PetitionCard = () => {
const StyledCard = withStyles({
root: { height: 450, width: 350 }
})(Card);
const [title, setTitle] = useState("");
const [description, setDescription] = useState("");
const [open, setOpen] = useState(false);
const [petition, newPetition] = useState(false);
const handleTitleChange = event => {
setTitle(event.target.value);
};
const handleDescriptionChange = event => setDescription(event.target.value);
const handleClose = (event, reason) => {
if (reason === "clickaway") {
return;
}
};
const Alert = props => <MuiAlert elevation={6} variant="filled" {...props} />;
const Message = (message, severity) => {
return (
<Snackbar open={!open} autoHideDuration={3000} onClose={handleClose}>
<Alert severity={severity}>{message}</Alert>
</Snackbar>
);
};
const clearField = event => {
setOpen(true);
if (title.length > 0 && description.length > 0) {
setTitle("");
setDescription("");
return (
<Message
open={open}
message={"You have successfully created a petition!"}
severity={"success"}
/>
);
} else {
return (
<Message
message={"You have one more more fields missing"}
severity={"error"}
/>
);
}
};
return (
<StyledCard>
<Box mt={1}>
<Grid container justify="center">
<TextField
id="outlined-multiline-static"
multiline
rows={1}
variant="outlined"
placeholder="Title"
value={title}
onChange={handleTitleChange}
/>
</Grid>
</Box>
<CardMedia title="Petition" style={{ height: 0, paddingTop: "40.25%" }} />
<Box mt={1} justify="center">
<Grid container justify="center">
<TextField
size="small"
inputProps={{
style: { fontSize: 15 }
}}
id="outlined-multiline-static"
multiline
rows={5}
placeholder="Description"
variant="outlined"
value={description}
onChange={handleDescriptionChange}
/>
</Grid>
</Box>
<Box mt={1}>
<Grid container justify="center">
<Button onClick={clearField}>
<CreateIcon />
Create Petition!
</Button>
</Grid>
</Box>
</StyledCard>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(
<React.StrictMode>
<PetitionCard />
</React.StrictMode>,
rootElement
);
The problem is that you are re-creating StyledCard whenever PetitionCard is rendered:
const PetitionCard = () => {
const StyledCard = withStyles({
root: { height: 450, width: 350 }
})(Card);
[...]
}
Therefore, a new TextField is created on every render since its container changes. TextField is by default not focused and doesn't know whether the TextField from the previous render was focused.
The solution is to create StyledCard outside PetitionCard:
const StyledCard = withStyles({
root: { height: 450, width: 350 }
})(Card);
const PetitionCard = () => {
[...]
}

Categories