why is my code showing wrong output for
as the rows has been already populated after adding it with the handletabledata function
My code is having a table and there is a add button where we add users but on the delete function when I am trying to see the rows I am getting only that row and rows above it.
please help.
import React from 'react'
import './server.scss'
import Paper from '#mui/material/Paper';
import Table from '#mui/material/Table';
import TableBody from '#mui/material/TableBody';
import TableCell from '#mui/material/TableCell';
import TableContainer from '#mui/material/TableContainer';
import TableHead from '#mui/material/TableHead';
import TablePagination from '#mui/material/TablePagination';
import TableRow from '#mui/material/TableRow';
import { Button } from '#mui/material';
import DeleteOutlineIcon from '#mui/icons-material/DeleteOutline';
import Dialog from '#mui/material/Dialog';
import DialogActions from '#mui/material/DialogActions';
import DialogContent from '#mui/material/DialogContent';
import DialogContentText from '#mui/material/DialogContentText';
import DialogTitle from '#mui/material/DialogTitle';
import Slide from '#mui/material/Slide';
import PersonAddAltIcon from '#mui/icons-material/PersonAddAlt';
import TextField from '#mui/material/TextField';
import InputLabel from '#mui/material/InputLabel';
import MenuItem from '#mui/material/MenuItem';
import FormControl from '#mui/material/FormControl';
import Select from '#mui/material/Select';
const columns = [
{ id: 'key', label: '#', minWidth: 70 },
{ id: 'user', label: 'User', minWidth: 100 },
{
id: 'signed',
label: 'Last Signed in',
minWidth: 170,
align: 'right',
},
{
id: 'role',
label: 'Role',
minWidth: 170,
align: 'right',
},
{
id: 'icon',
label: '',
minWidth: 170,
align: 'right',
},
];
function createData(user, role, key, icon, signed) {
signed = signed.getTime()
return { key, user, signed, role, icon };
}
//modal code
const Transition = React.forwardRef(function Transition(props, ref) {
return <Slide direction="up" ref={ref} {...props} />;
});
const Server = () => {
//final insertion of data
const [rows, setrow] = React.useState([]);
// console.log(rows)
//pagination
const [page, setPage] = React.useState(0);
const [rowsPerPage, setRowsPerPage] = React.useState(10);
const handleChangePage = (event, newPage) => {
setPage(newPage);
};
const handleChangeRowsPerPage = (event) => {
setRowsPerPage(+event.target.value);
setPage(0);
};
//modal code
const [open, setOpen] = React.useState(false);
const handleClickOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
//setting data for row
const [id, setid] = React.useState(0);
const handletabledata = () => {
setid(id + 1)
let row = [...rows]
row.push(createData(email, role, id, <DeleteOutlineIcon onClick={console.log(rows)}/>, new Date()))
setrow(row)
setemail('')
setrole('')
setOpen(false);
}
//input field
const [email, setemail] = React.useState('');
const handleEmail = (event) => {
setemail(event.target.value);
};
//dropdown list
const [role, setrole] = React.useState('');
const handleChange = (event) => {
setrole(event.target.value);
};
return (
<div className='server_main'>
<div className='addUser'>
<Button variant="contained" onClick={handleClickOpen}>Add User</Button>
<Dialog
open={open}
TransitionComponent={Transition}
keepMounted
onClose={handleClose}
aria-describedby="alert-dialog-slide-description"
fullWidth={true}
>
<DialogTitle>{"Add User"}</DialogTitle>
<DialogContent>
<DialogContentText id="alert-dialog-slide-description">
<div style={{ display: 'flex', height: '250px', justifyContent: 'space-around' }}>
<div >
<PersonAddAltIcon style={{ fontSize: '7rem', position: 'relative', top: '50px' }} />
</div>
<div style={{ display: 'flex', flexDirection: 'column', justifyContent: 'space-around' }}>
<span style={{ padding: '10px', position: 'relative', left: '10px', top: '10px' }}>User Information</span>
<TextField placeholder="Email Address" onChange={handleEmail} value={email} />
<FormControl fullWidth>
<InputLabel id="demo-simple-select-label">Role</InputLabel>
<Select
labelId="demo-simple-select-label"
id="demo-simple-select"
value={role}
label="role"
onChange={handleChange}
>
<MenuItem value={'Owner'}>Owner</MenuItem>
<MenuItem value={'Sales'}>Sales</MenuItem>
<MenuItem value={'Admin'}>Admin</MenuItem>
</Select>
</FormControl>
</div>
</div>
</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={handleClose}>Cancel</Button>
<Button onClick={handletabledata}>Add</Button>
</DialogActions>
</Dialog>
</div>
<Paper sx={{ width: '100%', overflow: 'hidden' }}>
<TableContainer sx={{ maxHeight: 440 }}>
<Table stickyHeader aria-label="sticky table">
<TableHead>
<TableRow>
{columns.map((column) => (
<TableCell
key={column.id}
align={column.align}
style={{ minWidth: column.minWidth }}
>
{column.label}
</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
{rows
.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
.map((row) => {
return (
<TableRow hover role="checkbox" tabIndex={-1} key={row.code}>
{columns.map((column) => {
const value = row[column.id];
return (
<TableCell key={column.id} align={column.align}>
{column.format && typeof value === 'number'
? column.format(value)
: value}
</TableCell>
);
})}
</TableRow>
);
})}
</TableBody>
</Table>
</TableContainer>
<TablePagination
rowsPerPageOptions={[10, 25, 100]}
component="div"
count={rows.length}
rowsPerPage={rowsPerPage}
page={page}
onPageChange={handleChangePage}
onRowsPerPageChange={handleChangeRowsPerPage}
/>
</Paper>
</div>
);
}
export default Server
Related
I'm working on a React router project and I can't seem to pass my function up to the App component. I've tried using the useLocation hook, but that only worked for receiving props from the App component. Any help is greatly appreciated, code is as follows:
File structure:
src:
-- App.jsx
-- Forms.jsx
-- Orders.jsx
App.jsx
import { useEffect, useState } from 'react';
import { BrowserRouter as Router, Routes, Route, Link } from 'react-router-dom';
import { Button, Typography } from '#mui/material';
import Form from './Form.jsx';
import Orders from './Orders.jsx';
import Error from './Error.jsx';
import './App.css';
const starterOrders = [
{
firstName: 'Billy',
lastName: 'Gibbons',
orderId: 'ZZTop0000001',
productName: 'Hat',
quantity: 2,
price: 14.99,
},
{
firstName: 'Dusty',
lastName: 'Hill',
orderId: 'ZZTop0000002',
productName: 'Shirt',
quantity: 1,
price: 19.99,
},
{
firstName: 'Frank',
lastName: 'Beard',
orderId: 'ZZTop0000003',
productName: 'Hat',
quantity: 2,
price: 29.98,
},
{
firstName: 'David',
lastName: 'Bowie',
orderId: 'UndrPr3ssr81',
productName: 'Sweatshirt',
quantity: 1,
price: 29.98,
},
];
const navBackgroundStyles = {
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
backgroundColor: 'rgb(255, 255, 255)',
};
function App() {
const [orders, setOrders] = useState(starterOrders);
useEffect(() => {
const cachedData = window.localStorage.getItem('ORDERS_ARRAY');
if (cachedData?.length) {
setOrders(JSON.parse(cachedData));
}
}, [])
const newOrderFunc = (order) => {
setOrders((prevOrders) => {
const newOrders = [order, ...prevOrders]
window.localStorage.setItem("ORDERS_ARRAY", JSON.stringify(newOrders));
return newOrders;
});
};
return (
<Router>
<div style={navBackgroundStyles}>
<div>
<Typography
sx={{
marginLeft: '1rem',
fontSize: '2rem',
color: 'rgb(33, 150, 243)',
}}
>
Clothing Co.
</Typography>
</div>
<div>
<Link to="/" state={{ onSaveOrderData: newOrderFunc }}>
<Button sx={{ marginRight: '1rem' }} variant="text">
Place Order
</Button>
</Link>
<Link to="/orders" state={{ orders: orders }}>
<Button sx={{ marginRight: '1rem' }} variant="text">
Orders
</Button>
</Link>
</div>
</div>
<Routes>
<Route path="/" element={<Form />} />
<Route path="/orders" element={<Orders />} />
<Route path="/*" element={<Error />} />
</Routes>
</Router>
);
}
export default App;
Form.jsx
import { useEffect, useState } from 'react';
import { useLocation } from 'react-router-dom';
import {
Alert,
Box,
Button,
InputAdornment,
InputLabel,
MenuItem,
OutlinedInput,
Select,
Slide,
TextField,
} from '#mui/material';
export default function Form({ onSaveOrderData }) {
const location = useLocation();
const saveFunction = location.state?.onSaveOrderData;
const [isActive, setIsActive] = useState(false);
const [firstName, setFirstName] = useState('');
const [lastName, setLastName] = useState('');
const [product, setProduct] = useState('');
const [quantity, setQuantity] = useState('');
const [price, setPrice] = useState('');
const quantityMenu = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// Generate random Order IDs
const makeId = () => {
var result = '';
var characters =
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
for (let i = 0; i < 12; i++) {
result += characters.charAt(
Math.floor(Math.random() * characters.length)
);
}
return result;
};
// Converts product value integer to product name
const productName = () => {
switch (product) {
case 1:
return 'Shirt';
case 2:
return 'Hat';
case 3:
return 'Sweatshirt';
}
};
// Calculates order cost on change of product or quantity state
useEffect(() => {
if (quantity > 0) {
switch (product) {
case 1:
setPrice((19.99 * quantity).toFixed(2));
break;
case 2:
setPrice((14.99 * quantity).toFixed(2));
break;
case 3:
setPrice((29.98 * quantity).toFixed(2));
break;
}
}
}, [product, quantity]);
// Sends new order to App, resets form fields
const submitHandler = (e) => {
e.preventDefault();
const newOrder = {
firstName: firstName,
lastName: lastName,
orderId: makeId(),
productName: productName(),
quantity: quantity,
price: price,
};
setIsActive(true);
saveFunction(newOrder);
setFirstName('');
setLastName('');
setProduct('');
setQuantity('');
setPrice('');
};
return (
<div
style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: '90vh'
}}
>
<div style={{ position: 'fixed', top: '60px', right: '10px' }}>
<Slide direction="left" in={isActive} mountOnEnter unmountOnExit>
<Alert
severity="success"
onClose={() => setIsActive(false)}
style={{ display: isActive ? 'flex' : 'none' }}
>
Thank you for your order!
</Alert>
</Slide>
</div>
<Box
sx={{
padding: '2rem',
width: 'fit-content',
border: '1px solid rgb(148, 148, 148)',
borderRadius: '5px',
backgroundColor: 'rgb(255, 255, 255)',
}}
>
<TextField
label="First Name"
variant="standard"
fullWidth
sx={{ marginRight: '5px' }}
value={firstName}
onChange={(e) => setFirstName(e.target.value)}
/>
<TextField
label="Last Name"
variant="standard"
fullWidth
sx={{ marginRight: '5px' }}
value={lastName}
onChange={(e) => setLastName(e.target.value)}
/>
<InputLabel
style={{
display: 'block',
margin: '1rem 0 0',
color: 'rgb(102, 102, 102)',
}}
>
Product
</InputLabel>
<Select
fullWidth
value={product}
onChange={(e) => setProduct(e.target.value)}
>
<MenuItem value="">
<em>Select product</em>
</MenuItem>
<MenuItem value={1}>Shirt</MenuItem>
<MenuItem value={2}>Hat</MenuItem>
<MenuItem value={3}>Sweatshirt</MenuItem>
</Select>
<InputLabel
style={{
display: 'inline-block',
margin: '1rem 0 0',
color: 'rgb(102, 102, 102)',
}}
>
Quantity
</InputLabel>
<Select
fullWidth
value={quantity}
onChange={(e) => setQuantity(e.target.value)}
>
<MenuItem value="">
<em>Select quantity</em>
</MenuItem>
{quantityMenu.map((item) => {
return (
<MenuItem key={item} value={item}>
{item}
</MenuItem>
);
})}
</Select>
<InputLabel
htmlFor="outlined-adornment-amount"
sx={{ margin: '1rem 0 0' }}
>
Amount
</InputLabel>
<OutlinedInput
fullWidth
value={price}
startAdornment={<InputAdornment position="start">$</InputAdornment>}
inputProps={{ readOnly: true }}
/>
<Button
variant="outlined"
fullWidth
sx={{
marginTop: '1.25rem',
fontSize: '1rem',
color: 'dark',
}}
onClick={submitHandler}
>
Place Order
</Button>
</Box>
</div>
);
}
Orders.jsx
import React from 'react';
import { useLocation } from 'react-router-dom';
import {
Paper,
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TableRow,
Typography,
} from '#mui/material';
export default function Orders({orders}) {
const location = useLocation();
const ordersList = location.state?.orders;
return (
<TableContainer component={Paper}>
<Typography variant="h1">Orders</Typography>
<Table sx={{ minWidth: 600 }} aria-label="simple table">
<TableHead>
<TableRow>
<TableCell>First Name</TableCell>
<TableCell>Last Name</TableCell>
<TableCell>Order ID</TableCell>
<TableCell>Product Name</TableCell>
<TableCell>Quantity</TableCell>
<TableCell>Price</TableCell>
</TableRow>
</TableHead>
<TableBody>
{ordersList.map((order) => (
<TableRow
key={order.orderId}
sx={{ '&:last-child td, &:last-child th': { border: 0 } }}
>
<TableCell scope="row">{order.firstName}</TableCell>
<TableCell scope="row">{order.lastName}</TableCell>
<TableCell>{order.orderId}</TableCell>
<TableCell>{order.productName}</TableCell>
<TableCell>{order.quantity}</TableCell>
<TableCell>{'$' + `${order.price}`}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
);
}
So far, I've tried using the useLocation hook as I did in the Orders component, as seen below. Truth be told, the destructured props are both greyed out so it doesn't look like they're being used. I followed a tutorial for passing state from App to component and it seemed to work for the Orders component.
Orders.jsx
export default function Orders({orders}) {
const location = useLocation();
const ordersList = location.state?.orders;
Form.jsx
export default function Form({ onSaveOrderData }) {
const location = useLocation();
const saveFunction = location.state?.onSaveOrderData;
I am using react
"react": "^18.2.0",
"#mui/material": "^5.10.7",
"#mui/x-data-grid-pro": "^5.16.0"
if I use custom pagination ,rowsPerPageOptions dropdown is not visible, if I use default pagination then rowsPerPageOptions dropdown is visible. Could you please help me with this.
import * as React from "react";
import Box from "#mui/material/Box";
import { DataGridPro, gridPageCountSelector,
gridPageSelector,
useGridApiContext,
useGridSelector } from "#mui/x-data-grid-pro";
import { useDemoData } from "#mui/x-data-grid-generator";
import { Pagination } from "#mui/material";
function CustomPagination() {
const apiRef = useGridApiContext();
const page = useGridSelector(apiRef, gridPageSelector);
const pageCount = useGridSelector(apiRef, gridPageCountSelector);
return (
<Pagination
color="primary"
count={pageCount}
page={page + 1}
onChange={(event, value) => apiRef.current.setPage(value - 1)}
variant="outlined" shape="rounded"
/>
);
}
export default function CustomPaginationGrid() {
const { data } = useDemoData({
dataSet: "Commodity",
rowLength: 50,
maxColumns: 6
});
return (
<Box sx={{ height: 400, width: "100%" }}>
<DataGridPro
pagination
pageSize={25}
rowsPerPageOptions={[25, 50, 100]}
components={{
Pagination: CustomPagination
}}
{...data}
checkboxSelection
disableSelectionOnClick
/>
</Box>
);
}
I solved it by custom rowsPerPageOptions dropdown, here is the solution.
CustomPagination.js file
import {
FormControl, InputLabel,
MenuItem,
Pagination,
Select,
Typography
} from "#mui/material";
import {
gridPageCountSelector,
gridPageSelector,
useGridApiContext,
useGridSelector
} from "#mui/x-data-grid-pro";
import * as React from "react";
import { CssBaseline } from "#mui/material";
import { Box } from "#mui/system";
export default function CustomPagination(props) {
const apiRef = useGridApiContext();
const cuttentPage = useGridSelector(apiRef, gridPageSelector);
const pageCount = useGridSelector(apiRef, gridPageCountSelector);
const [rowsPerPage, setRowsPerPage] = React.useState(25);
const handleChange = (event) => {
setRowsPerPage(event.target.value);
apiRef.current.setPageSize(event.target.value)
};
React.useEffect(() => {
apiRef.current.setPageSize(25)
}, []);
return (
<>
<CssBaseline />
<FormControl sx={{ m: 1, p: 0, mt: 1, minWidth: 80 }}>
<InputLabel id="demo-simple-select-label">Rows</InputLabel>
<Select
size="small"
labelId="demo-simple-select-label"
id="demo-simple-select"
label="Rows"
value={rowsPerPage}
onChange={handleChange}
>
<MenuItem value={25}>25</MenuItem>
<MenuItem value={50}>50</MenuItem>
<MenuItem value={100}>100</MenuItem>
<MenuItem value={200}>200</MenuItem>
</Select>
</FormControl>
<Box sx={{ flexGrow: 1 }} />
<Pagination
count={pageCount}
page={cuttentPage + 1}
variant="outlined" color="primary" shape="rounded"
onChange={(event, value) => apiRef.current.setPage(value - 1)}
/>
</>
);
}
and mui datagrid
const [pageSize, setPageSize] = React.useState(25);
const [pageNo, setPageNo] = React.useState(0);
const pagechangeCalled = (number) => {
setPageNo(number)
}
<Box sx={{ height: 600, minWidth: "100%" }}>
<DataGridPro
rows={data}
getRowId={(row) => row.ticsNumber}
columns={myincidentsColumns}
onRowDoubleClick={(ids) => someFunction(ids)}
onPageSizeChange={(newPageSize) => setPageSize(newPageSize)}
density="compact"
pagination
onPageChange={pagechangeCalled}
components={{ Toolbar: GridToolbar, Pagination: CustomPagination }}
componentsProps={{
toolbar: {
showQuickFilter: true,
quickFilterProps: { debounceMs: 500 },
},
}}
/>
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?
I have made a table with a search bar functionality, it filter the data when press the search button and reset the filter function and show unfilter data when click the clear button but it's not clearing the current input value from the display. however it clear the filetr function and show unfilter data. I tired setting state to empty string but still not able to clear the input value, I'm new in react need assistance to understand the issue
1. App.js having search bar and all the state and function
function App() {
const [searchTerm, setSearchTerm] = useState("");
const classes = useStyles();
const [buttonSearch, setButtonSearch] = useState("");
const getSearchTerm = (event) => {
let searchWord = event.target.value;
setSearchTerm(searchWord);
console.log(searchWord);
}
const doSearch = () => {
console.log('this is from the doSearch func', searchTerm)
setButtonSearch(searchTerm);
}
const clearSearch = () => {
console.log('im working')
setSearchTerm("");
setButtonSearch("");
}
return (
<div className="App">
<div className="wrapper">
<div className="container-table">
<div className="head">
<h5 className='management'>MANAGEMENT</h5>
<div className="head-middle">
<h2>Clients</h2>
<div className="button-collection">
<Button style={{ backgroundColor: '#5900B4', color: '#FFFFFF', fontSize: '15px', fontWeight: '900', width: '206px', height: '42px' }}
variant="contained"
className='add-collection-btn'
startIcon={<AddIcon />}
>
New Collection
</Button>
</div>
</div>
<div className="head-bottom">
<div className="head-button">
<div className="search">
<div className={classes.search}>
<div className={classes.searchIcon}>
<SearchIcon />
</div>
<InputBase
placeholder="Search..."
classes={{
root: classes.inputRoot,
input: classes.inputInput,
}}
onChange={getSearchTerm}
/>
</div>
</div>
<Button onClick={doSearch}
style={{ backgroundColor: 'white', color: 'black', width: '100px', height: '40px', marginLeft: '20px', marginRight: '20px' }} variant="contained">
Search
</Button>
<Button onClick={clearSearch}
style={{ backgroundColor: 'white', color: 'black', width: '100px', height: '40px' }} variant="contained">
Clear
</Button>
</div>
<Button
style={{ backgroundColor: 'transparent', color: '#5900B4', width: '206px', height: '42px', borderColor: '#5900B4', fontSize: '15px', fontWeight: '900' }}
variant="outlined" color="primary"
startIcon={<FilterListIcon />}
>
SHOW FILTER
</Button>
</div>
<div className="table">
<EnhancedTable
searchTerm={buttonSearch}
/>
</div>
</div>
</div>
</div>
</div>
);
}
2. table.js having filter and map function
export default function EnhancedTable(props) {
console.log("these r props for table component", props);
const { searchTerm } = props;
console.log("table searchTerm value", searchTerm)
const classes = useStyles();
const [order, setOrder] = React.useState('asc');
const [orderBy, setOrderBy] = React.useState('calories');
const [selected, setSelected] = React.useState([]);
const [page, setPage] = React.useState(0);
const [dense, setDense] = React.useState(false);
const [rowsPerPage, setRowsPerPage] = React.useState(5);
const isSelected = (name) => selected.indexOf(name) !== -1;
const [data, setData] = useState([]);
const getData = async () => {
try {
const data = await axios.get("something");
console.log('This is data from axios', data.data);
setData(data.data);
} catch (e) {
console.log("this is error for fetching data", e)
}
};
useEffect(() => {
getData();
}, [])
const filtered = useMemo(() => {
if (!searchTerm) {
return data;
}
const term = searchTerm.toLowerCase()
return data.filter(({ clientName, clientEmail }) => clientName.toLowerCase().includes(term)
|| clientEmail.toLowerCase().includes(term)
)
}, [data, searchTerm])
return (
<div className={classes.root}>
<Paper className={classes.paper}>
<EnhancedTableToolbar numSelected={selected.length} />
<TableContainer>
<Table
className={classes.table}
aria-labelledby="tableTitle"
size={dense ? 'small' : 'medium'}
aria-label="enhanced table"
>
<EnhancedTableHead
classes={classes}
numSelected={selected.length}
order={order}
orderBy={orderBy}
/>
<TableBody>
{filtered
.map((item, index) => {
return (
<TableRow
hover
role="checkbox"
tabIndex={-1}
>
<TableCell padding="checkbox">
<Checkbox
/>
</TableCell>
<TableCell component="th" scope="row" padding="none">{item.clientName}</TableCell>
<TableCell align="right">{item.clientEmail}</TableCell>
<TableCell align="right">{item.clientWorkPhone}</TableCell>
<TableCell align="right">{item.clientIndustry}</TableCell>
<TableCell align="right">{item.tenantId}</TableCell>
<TableCell align="right">{item.clientWebsite}</TableCell>
<TableCell align="right">
<Button style={{ backgroundColor: 'transparent', color: '#5900B4' }}
variant="outlined" color="primary" href="#outlined-buttons" >
{<CreateIcon />}
</Button>
</TableCell>
</TableRow>
)
})}
</TableBody>
</Table>
</TableContainer>
</Paper>
</div>
);
}
Try this option
<InputBase value={searchTerm}
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).