So I have a basic messenger chap application, the search bar to retrieve chats works fine whenever I type in letters, yet whenever I backspace, the event handler wont update, and I am left with the chat room lists that fit the search, even though the search bar is left empty.
Examples below
1.All chatrooms are shown below:
2.Typing "funny" filters a list with chatrooms labeled "funny":
3.Pressing backspace does not show all the chatrooms:
import { Avatar, IconButton } from '#material-ui/core';
import React, { useEffect, useState } from 'react';
import './Sidebar.css';
import SearchIcon from '#material-ui/icons/Search';
import { RateReviewOutlined } from '#material-ui/icons';
import { SidebarChat } from './SidebarChat';
import { useSelector } from 'react-redux';
import { selectUser } from './features/userSlice';
import db, { auth } from './firebase';
import { makeStyles } from '#material-ui/core/styles';
import Modal from '#material-ui/core/Modal';
import Backdrop from '#material-ui/core/Backdrop';
import Fade from '#material-ui/core/Fade';
const useStyles = makeStyles((theme) => ({
modal: {
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
},
paper: {
backgroundColor: theme.palette.background.paper,
border: '2px solid #000',
boxShadow: theme.shadows[5],
padding: theme.spacing(2, 4, 3),
},
}));
export function Sidebar(props) {
const user = useSelector(selectUser);
const [chats, setChats] = useState([]);
const classes = useStyles();
const [open, setOpen] = useState(false);
const [search, setSearch] = useState('');
const handleOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
useEffect(() => {
db.collection('chats').onSnapshot((snapshot) =>
setChats(
snapshot.docs.map((doc) => ({
id: doc.id,
data: doc.data(),
}))
)
);
}, []);
const addChat = () => {
const chatName = prompt('Please enter a chat name');
if (chatName) {
db.collection('chats').add({
chatName: chatName,
});
}
};
const searchFunction = (e) => {
setSearch(e);
console.log(search);
console.log(chats);
const filtered = chats.filter(chat => {
return chat.data.chatName.toLowerCase().includes(e.toLowerCase())
});
// console.log(filtered)
setChats(filtered);
};
return (
<div className="sidebar">
<div className="sidebar__header">
<Avatar
onClick={handleOpen}
src={user.photo}
className="sidebar__avatar"
/>
<div className="sidebar__input">
<SearchIcon />
<input
placeholder="Search"
value={search}
onChange={(e) => searchFunction(e.target.value)}
/>
</div>
<IconButton variant="outlined" className="sidebar__inputButton">
<RateReviewOutlined onClick={addChat} />
</IconButton>
</div>
<div className="sidebar__chats">
{chats.map(({ id, data: { chatName } }) => (
<SidebarChat key={id} id={id} chatName={chatName} />
))}
</div>
<Modal
aria-labelledby="transition-modal-title"
aria-describedby="transition-modal-description"
className={classes.modal}
open={open}
onClose={handleClose}
closeAfterTransition
BackdropComponent={Backdrop}
BackdropProps={{
timeout: 500,
}}
>
<Fade in={open}>
<div className={classes.paper}>
<h2 id="transition-modal-title">
Are you sure you want to sign out?
</h2>
<button onClick={() => auth.signOut()}>Yes</button>
<button onClick={handleClose}>No</button>
</div>
</Fade>
</Modal>
</div>
);
}
In your searchFunction it is constantly updating filtered to have less and less chatrooms. You could store chat rooms as a separate state and then filter that instead to preserve all chat rooms.
Related
We upgraded MUI from v4 to v5 and we have UI tests which started failing. Error is:
TypeError: Cannot read property 'secondary' of undefined (I added comment to which line in code this refers)
Test example:
describe('<AnonDragNDropFileUpload />', () => {
it('should render', () => {
const blob = () => {
return new File(['Test string'], 'Test file.txt');
};
const fileSet: AnonFileSet = {
originalFile: { get: blob, set: () => undefined },
compressedFile: { get: () => undefined, set: () => undefined },
};
const result = render(<AnonDragNDropFileUpload fileSet={fileSet} downloadFileAction={jest.fn()} clearFileAction={jest.fn()} />);
expect(result).toBeTruthy();
});
});
Code:
import { Paper } from '#mui/material';
import { green, red } from '#mui/material/colors';
import { lighten, Theme } from '#mui/material/styles';
import makeStyles from '#mui/styles/makeStyles';
import { JobInputFileTypeEnum } from 'app/api';
import React, { useCallback, useEffect, useState } from 'react';
import { useDropzone } from 'react-dropzone';
import { AnonFileSet } from '.';
const useDropZoneStyles = makeStyles((theme: Theme) => ({
dragndropZone: {
backgroundColor: lighten(theme.palette.secondary.light, 0.8), // <-- this line fails
width: '100%',
},
info: {
backgroundColor: green[100],
width: '100%',
},
}));
interface Props {
fileSet: AnonFileSet;
clearFileAction: (fileType?: JobInputFileTypeEnum) => void;
downloadFileAction: () => void;
}
export const AnonDragNDropFileUpload: React.FC<Props> = ({ fileSet, clearFileAction, downloadFileAction }) => {
const classes = useDropZoneStyles();
const [fileLabel, setFileLabel] = useState('');
const onDrop = useCallback(async (acceptedFiles: File[]) => {
setFileLabel(fileSet.originalFile.get()?.name ?? '');
fileSet.originalFile.set(acceptedFiles[0]);
}, []);
const { acceptedFiles, getRootProps, getInputProps } = useDropzone({ onDrop, multiple: false, accept: '.csv' });
const { ref, ...rootProps } = getRootProps();
const handleDeleteFile = () => {
acceptedFiles.splice(
acceptedFiles.findIndex((x) => x.name === fileSet.originalFile.get()?.name),
1,
);
clearFileAction();
};
useEffect(() => {
setFileLabel(fileSet.originalFile.get()?.name ?? '');
}, [fileSet.originalFile.get()]);
if (fileSet.originalFile.get())
return (
<Paper variant="outlined">
<div className="flex px-8 py-32 justify-center">
<div className="flex">
<a style={{ color: '#888888', textDecoration: 'underline', cursor: 'default' }}>{fileLabel}</a>
<p className="mx-4"> </p>
<a onClick={handleDeleteFile} style={{ color: red[600], cursor: 'pointer' }} role="link">
{'[Clear File]'}
</a>
<p className="mx-4"> </p>
{fileSet.compressedFile?.get() && (
<a onClick={downloadFileAction} style={{ color: green[600], cursor: 'pointer' }} role="link">
{'[Download File]'}
</a>
)}
</div>
</div>
</Paper>
);
return (
<Paper {...rootProps} className={classes.dragndropZone} variant="outlined">
<div className="flex px-8 py-32 justify-center">
<input {...getInputProps()} name="customerCSVFilename" placeholder="CSV File"/>
<p>{fileLabel}</p>
</div>
</Paper>
);
};
What I've tried so far:
Checked if ThemeProvider is available
Added custom theme just to the code block which fails
All other tests which are testing hooks or custom logic (like pure TypeScript) are working without any issues, but it seems that somehow using styles from MUI is not working. When I remove these lines, test is passing, so my guess it has something with MUI makeStyles.
Any ideas? Thanks for helping me out.
Try to use a mocked component, wrapped inside a ThemeProvider instance:
import theme from './path/to/your/theme'
const MockAnonDragNDropFileUpload = (props: any) => {
return (
<ThemeProvider theme={theme}>
<AnonDragNDropFileUpload {...props} />
</ThemeProvider>
);
}
To mock the component using the existing theme you could separate its declaration into a distinct file:
const theme = createTheme({
...
});
export default theme;
Then use the mocked instance in the tests:
describe('<AnonDragNDropFileUpload />', () => {
it('should render', () => {
...
const result = render(
<MockAnonDragNDropFileUpload
fileSet={fileSet}
downloadFileAction={jest.fn()}
clearFileAction={jest.fn()}
/>
);
expect(result).toBeTruthy();
});
});
I am trying to create a modal that will display all the data on the element clicked.
For exemple, if i clicked the id(367) of a movie, it will display the title, the genres and the released date.
First i created a Context.js that will send data in the component Movie.js:
Context.js
import React, { useState, useEffect, createContext } from "react";
import { getAxios } from "../Function/index";
const MovieContext = createContext();
const MovieProvider = ({ children }) => {
const [datas, setDatas] = useState([]);
const [testdatas, testsetDatas] = useState([]);
const getMovie = async () => {
const data = await getAxios(
"https://api.themoviedb.org/3/movie/upcoming?api_key={}"
);
setDatas(data.results);
};
useEffect(() => {
getMovie();
}, []);
return (
<MovieContext.Provider value={{ datas, testdatas }}>{children}</MovieContext.Provider>
);
};
export { MovieContext, MovieProvider };
Movie.js
import React, { useContext } from "react";
import { MovieContext } from '../Context'
import { Card, Row, Tag } from 'antd'
const Main = () => {
const { datas } = useContext(MovieContext)
return (
<Row gutter={16}>
{datas.map((item, id) => (
<Card
key={id}
style={{ width: 300, margin: 10 }} bordered={true}
hoverable
>
<div>
<p style={{ textAlign: "left" }}>{item.title} <span style={{ float: "right" }}>{item.vote_average}</span></p>
</div>
<p><img src={`https://image.tmdb.org/t/p/w500/${item.poster_path}`} alt="#" width="200" height="200" /></p>
<Tag color="red"> {item.title}</Tag>
</Card>
))}
</Row >
);
};
export default Main;
I am using material UI and I think the default import of component has black borders. I want to make it so the box is all white with no black borders. Is there a code snippet I can addon to my code to make the black borders go away?
Current outcome
Desired outcome, see how there are no black borders?
code
import { Avatar, IconButton } from '#material-ui/core';
import React, { useEffect, useState } from 'react';
import './Sidebar.css';
import SearchIcon from '#material-ui/icons/Search';
import { RateReviewOutlined } from '#material-ui/icons';
import { SidebarChat } from './SidebarChat';
import { useSelector } from 'react-redux';
import { selectUser } from './features/userSlice';
import db, { auth } from './firebase';
import { makeStyles } from '#material-ui/core/styles';
import Modal from '#material-ui/core/Modal';
import Backdrop from '#material-ui/core/Backdrop';
import Fade from '#material-ui/core/Fade';
import Card from '#material-ui/core/Card';
import CardActionArea from '#material-ui/core/CardActionArea';
import CardActions from '#material-ui/core/CardActions';
import CardContent from '#material-ui/core/CardContent';
import Button from '#material-ui/core/Button';
import Typography from '#material-ui/core/Typography';
const useStyles = makeStyles((theme) => ({
modal: {
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
},
root: {
maxWidth: 345,
},
media: {
height: 140,
},
}));
export function Sidebar(props) {
const user = useSelector(selectUser);
const [chats, setChats] = useState([]);
const [filterChats, setFilteredChats] = useState([]);
const classes = useStyles();
const [search, setSearch] = useState('');
const [open, setOpen] = useState(false);
const handleOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
useEffect(() => {
db.collection('chats').onSnapshot((snapshot) =>
setChats(
snapshot.docs.map((doc) => ({
id: doc.id,
data: doc.data(),
}))
)
);
db.collection('chats').onSnapshot((snapshot) =>
setFilteredChats(
snapshot.docs.map((doc) => ({
id: doc.id,
data: doc.data(),
}))
)
);
}, []);
const addChat = () => {
const chatName = prompt('Please enter a chat name');
if (chatName) {
db.collection('chats').add({
chatName: chatName,
});
}
};
const searchFunction = (e) => {
setSearch(e);
const filtered = chats.filter(chat => {
return chat.data.chatName.toLowerCase().includes(e.toLowerCase())
});
setFilteredChats(filtered);
};
return (
<div className="sidebar">
<div className="sidebar__header">
<Avatar
onClick={handleOpen}
src={user.photo}
className="sidebar__avatar"
/>
<div className="sidebar__input">
<SearchIcon />
<input
placeholder="Search"
value={search}
onChange={(e) => searchFunction(e.target.value)}
/>
</div>
<IconButton variant="outlined" className="sidebar__inputButton">
<RateReviewOutlined onClick={addChat} />
</IconButton>
</div>
<div className="sidebar__chats">
{filterChats.map(({ id, data: { chatName } }) => (
<SidebarChat key={id} id={id} chatName={chatName} />
))}
</div>
<Modal
style={{border: '2px solid #FFFFFF',}}
aria-labelledby="transition-modal-title"
aria-describedby="transition-modal-description"
className={classes.modal}
open={open}
onClose={handleClose}
closeAfterTransition
BackdropComponent={Backdrop}
BackdropProps={{
timeout: 500,
}}
>
<Fade in={open}>
<Card className={classes.root}>
<CardActionArea>
<CardContent>
<Typography gutterBottom variant="h5" component="h2">
{user.displayName.split(' ').slice(0,1).join(' ')},
</Typography>
<Typography variant="body2" color="textSecondary" component="p">
Are you sure you want to sign out?
</Typography>
</CardContent>
</CardActionArea>
<CardActions>
<Button onClick={() => auth.signOut()} size="small" color="primary">
Yes
</Button>
<Button onClick={handleClose} size="small" color="primary">
No
</Button>
</CardActions>
</Card>
</Fade>
</Modal>
</div>
);
}
answer below - switched material ui from Modal to Dialog
import { Avatar, IconButton } from '#material-ui/core';
import React, { useEffect, useState } from 'react';
import './Sidebar.css';
import SearchIcon from '#material-ui/icons/Search';
import { RateReviewOutlined } from '#material-ui/icons';
import { SidebarChat } from './SidebarChat';
import { useSelector } from 'react-redux';
import { selectUser } from './features/userSlice';
import db, { auth } from './firebase';
import { makeStyles } from '#material-ui/core/styles';
import Button from '#material-ui/core/Button';
import Dialog from '#material-ui/core/Dialog';
import DialogActions from '#material-ui/core/DialogActions';
import DialogContent from '#material-ui/core/DialogContent';
import DialogContentText from '#material-ui/core/DialogContentText';
import DialogTitle from '#material-ui/core/DialogTitle';
export function Sidebar(props) {
const user = useSelector(selectUser);
const [chats, setChats] = useState([]);
const [filterChats, setFilteredChats] = useState([]);
const [search, setSearch] = useState('');
const [open, setOpen] = useState(false);
const handleOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
useEffect(() => {
db.collection('chats').onSnapshot((snapshot) =>
setChats(
snapshot.docs.map((doc) => ({
id: doc.id,
data: doc.data(),
}))
)
);
db.collection('chats').onSnapshot((snapshot) =>
setFilteredChats(
snapshot.docs.map((doc) => ({
id: doc.id,
data: doc.data(),
}))
)
);
}, []);
const addChat = () => {
const chatName = prompt('Please enter a chat name');
if (chatName) {
db.collection('chats').add({
chatName: chatName,
});
}
};
const searchFunction = (e) => {
setSearch(e);
const filtered = chats.filter(chat => {
return chat.data.chatName.toLowerCase().includes(e.toLowerCase())
});
setFilteredChats(filtered);
};
return (
<div className="sidebar">
<div className="sidebar__header">
<Avatar
onClick={handleOpen}
src={user.photo}
className="sidebar__avatar"
/>
<div className="sidebar__input">
<SearchIcon />
<input
placeholder="Search"
value={search}
onChange={(e) => searchFunction(e.target.value)}
/>
</div>
<IconButton variant="outlined" className="sidebar__inputButton">
<RateReviewOutlined onClick={addChat} />
</IconButton>
</div>
<div className="sidebar__chats">
{filterChats.map(({ id, data: { chatName } }) => (
<SidebarChat key={id} id={id} chatName={chatName} />
))}
</div>
<Dialog
open={open}
onClose={handleClose}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
>
<DialogTitle id="alert-dialog-title">{`${user.displayName.split(' ').slice(0,1).join(' ')},`}</DialogTitle>
<DialogContent>
<DialogContentText id="alert-dialog-description">
Are you sure you want to sign out?
</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={() => auth.signOut()} color="primary">
Yes
</Button>
<Button onClick={handleClose} color="primary" autoFocus>
No
</Button>
</DialogActions>
</Dialog>
</div>
);
}
So I have a basic messenger chat application with a search bar to retrieve chatrooms, and it works fine whenever I type in letters, yet whenever I backspace, why wont it retrieve the list I had previous?
Examples below
1.All chatrooms are shown below:
2.Typing "funny" filters a list with chatrooms labeled "funny":
3.Pressing backspace does not show all the chatrooms:
import { Avatar, IconButton } from '#material-ui/core';
import React, { useEffect, useState } from 'react';
import './Sidebar.css';
import SearchIcon from '#material-ui/icons/Search';
import { RateReviewOutlined } from '#material-ui/icons';
import { SidebarChat } from './SidebarChat';
import { useSelector } from 'react-redux';
import { selectUser } from './features/userSlice';
import db, { auth } from './firebase';
import { makeStyles } from '#material-ui/core/styles';
import Modal from '#material-ui/core/Modal';
import Backdrop from '#material-ui/core/Backdrop';
import Fade from '#material-ui/core/Fade';
const useStyles = makeStyles((theme) => ({
modal: {
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
},
paper: {
backgroundColor: theme.palette.background.paper,
border: '2px solid #000',
boxShadow: theme.shadows[5],
padding: theme.spacing(2, 4, 3),
},
}));
export function Sidebar(props) {
const user = useSelector(selectUser);
const [chats, setChats] = useState([]);
const classes = useStyles();
const [open, setOpen] = useState(false);
const [search, setSearch] = useState('');
const handleOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
useEffect(() => {
db.collection('chats').onSnapshot((snapshot) =>
setChats(
snapshot.docs.map((doc) => ({
id: doc.id,
data: doc.data(),
}))
)
);
}, []);
const addChat = () => {
const chatName = prompt('Please enter a chat name');
if (chatName) {
db.collection('chats').add({
chatName: chatName,
});
}
};
const searchFunction = (e) => {
setSearch(e);
console.log(search);
console.log(chats);
const filtered = chats.filter(chat => {
return chat.data.chatName.toLowerCase().includes(e.toLowerCase())
});
// console.log(filtered)
setChats(filtered);
};
return (
<div className="sidebar">
<div className="sidebar__header">
<Avatar
onClick={handleOpen}
src={user.photo}
className="sidebar__avatar"
/>
<div className="sidebar__input">
<SearchIcon />
<input
placeholder="Search"
value={search}
onChange={(e) => searchFunction(e.target.value)}
/>
</div>
<IconButton variant="outlined" className="sidebar__inputButton">
<RateReviewOutlined onClick={addChat} />
</IconButton>
</div>
<div className="sidebar__chats">
{chats.map(({ id, data: { chatName } }) => (
<SidebarChat key={id} id={id} chatName={chatName} />
))}
</div>
<Modal
aria-labelledby="transition-modal-title"
aria-describedby="transition-modal-description"
className={classes.modal}
open={open}
onClose={handleClose}
closeAfterTransition
BackdropComponent={Backdrop}
BackdropProps={{
timeout: 500,
}}
>
<Fade in={open}>
<div className={classes.paper}>
<h2 id="transition-modal-title">
Are you sure you want to sign out?
</h2>
<button onClick={() => auth.signOut()}>Yes</button>
<button onClick={handleClose}>No</button>
</div>
</Fade>
</Modal>
</div>
);
}
You need to save the initial list of chats in a variable and once the search is set to blank '' you need to update your chats with the initial saved chats.
Problem here is -
const filtered = chats.filter(chat => {
return chat.data.chatName.toLowerCase().includes(e.toLowerCase())
});
// console.log(filtered)
setChats(filtered);
I am fetching array of objects from an API endpoint,
I am using react-redux for state management.
I have two problems.
data gets fetched but only loads and displays after I refresh the page.
console logging single statement 4 times 2 blank array before setting state and 2 with data after setting state where it should have been only once I guess.
Following is my code.
Dashboard Action
import dashboardAPI from "../../../API/ShopUserAPI/dashboardAPI"
export const CURRENT_ORDER_LOAD = "CURRENT_ORDER_LOAD"
export const CURRENT_ORDER_FETCH = "CURRENT_ORDER_FETCH"
export const CURRENT_ORDER_ERROR = "CURRENT_ORDER_ERROR"
export const currentOrderAction = () => {
return dispatch => {
dispatch({ type: CURRENT_ORDER_LOAD, payload: '' })
dashboardAPI.get('/orders')
.then(resp => {
console.log(resp)
dispatch({ type: CURRENT_ORDER_FETCH, payload: resp.data.data.orders })
})
.catch(err => {
console.log(err)
dispatch({ type: CURRENT_ORDER_ERROR, payload: 'error occured. Retry !' })
})
}
}
Dashboard Reducer
import { CURRENT_ORDER_LOAD, CURRENT_ORDER_FETCH, CURRENT_ORDER_ERROR } from "../actions/dashboardActions";
const initialState = {
isLoading: true,
currentOrderData: [],
currentOrdererror: ''
}
const dashboardReducer = (state = initialState, action) => {
switch (action.type) {
case CURRENT_ORDER_LOAD:
return {
...state,
isLoading: true
}
case CURRENT_ORDER_FETCH:
return {
...state,
isLoading: false,
currentOrderData: action.payload
}
case CURRENT_ORDER_ERROR:
return {
...state,
isLoading: false,
currentOrdererror: action.payload
}
default:
return state
}
}
export default dashboardReducer
Dashboard page
import React from 'react'
import { Link } from 'react-router-dom'
import { makeStyles } from '#material-ui/core/styles';
import { Button, Typography, Grid, DialogContent, DialogActions, Dialog, DialogTitle, Divider, ExpansionPanel, ExpansionPanelSummary, ExpansionPanelDetails } from "#material-ui/core";
import ExpandMoreIcon from '#material-ui/icons/ExpandMore';
import { connect } from "react-redux";
const useStyles = makeStyles((theme) => ({
contentCenter: {
display: 'flex',
justifyContent: 'center',
marginTop: '1rem'
},
newSection: {
marginTop: '1rem'
},
innerSection: {
padding: '1rem'
},
heading: {
fontSize: theme.typography.pxToRem(15),
color: theme.palette.text.secondary,
},
secondaryHeading: {
fontSize: theme.typography.pxToRem(15),
color: theme.palette.text.secondary,
},
}))
const CurrentOrders = (props) => {
console.log(props.currentOrderData) // console.log printing 4 times
const [expanded, setExpanded] = React.useState(false);
const handleChange = (panel) => (event, isExpanded) => {
setExpanded(isExpanded ? panel : false);
};
const classes = useStyles()
return (
<div className={classes.newSection}>
{/* current orders list */}
<Typography className={classes.contentCenter}>
Current orders
</Typography>
{/* Orders expansion panel list */}
{props.currentOrderData.map(currentOrders => (
<ExpansionPanel expanded={expanded === 'panel1'} onChange={handleChange('panel1')} className={classes.newSection}>
<ExpansionPanelSummary
expandIcon={<ExpandMoreIcon />}
aria-controls="panel1bh-content"
id="panel1bh-header"
>
<Typography className={classes.heading}>Order ID: #{currentOrders.orderID}</Typography>
</ExpansionPanelSummary>
<ExpansionPanelDetails>
<Grid container justify="space-between">
<Grid item>
<Link to="/order" style={{ textDecoration: "none" }}>
<Button size="small" variant="contained" color="primary">
View Order
</Button>
</Link>
</Grid>
</Grid>
</ExpansionPanelDetails>
</ExpansionPanel>
))}
</div>
)
}
const mapStateToProps = state => {
return {
currentOrderData: state.dashboard.currentOrderData
}
}
export default connect(mapStateToProps)(CurrentOrders)
I've dispatched dashboard action in the parent component of this page
DIspatching of Dashboard
import React, { useEffect } from "react";
import { Container } from "#material-ui/core";
import CurrentOrders from "./CurrentOrders";
import TodaysOrders from "./TodaysOrders";
import { makeStyles } from '#material-ui/core/styles';
import { Button, Typography, Grid, DialogContent, DialogActions, Dialog, DialogTitle, Divider } from "#material-ui/core";
import { connect } from "react-redux";
import { currentOrderAction } from "../../../store/ShopUserStore/actions/dashboardActions";
const useStyles = makeStyles((theme) => ({
contentCenter: {
display: 'flex',
justifyContent: 'center',
marginTop: '1rem'
},
newSection: {
marginTop: '1rem'
},
innerSection: {
padding: '1rem'
},
buttonSuccess: {
color: theme.palette.success.main
}
}))
const Home = (props) => {
const [open, setOpen] = React.useState(false);
useEffect(() => {
props.getCurrentOrders()
})
const handleClickOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
const classes = useStyles()
return (
<div>
<Container>
{/* shop status */}
<Grid container justify="flex-start" className={classes.newSection}>
<Button variant="outlined" color="primary" onClick={handleClickOpen} className={classes.buttonSuccess}>
Online
</Button>
</Grid>
{/* shop status confirmation dialog */}
<Dialog onClose={handleClose} aria-labelledby="customized-dialog-title" open={open}>
<DialogTitle id="customized-dialog-title" onClose={handleClose}>
Shop status
</DialogTitle>
<Divider />
<DialogContent>
<Typography className={classes.newSection}>
Are you sure that you want to change shop status ?
</Typography>
</DialogContent>
<DialogActions>
<Button autoFocus onClick={handleClose} color="primary">
No
</Button>
<Button autoFocus onClick={handleClose} color="primary">
Yes
</Button>
</DialogActions>
</Dialog>
<Grid container spacing={3}
>
<Grid item xs={12} md={6}>
<CurrentOrders />
</Grid>
<Grid item xs={12} md={6}>
<TodaysOrders />
</Grid>
</Grid>
</Container>
</div>
)
}
const mapDispatchToProps = (dispatch) => {
return {
getCurrentOrders: () => dispatch(currentOrderAction())
}
}
export default connect(null, mapDispatchToProps)(Home)
When you run your application, you should stumble into a nasty loop. The effect hook runs when the component mounts but also when the component updates. Because we are setting the state after every data fetch, the component updates and the effect runs again. It fetches the data again and again. That's a bug and needs to be avoided. We only want to fetch data when the component mounts. That's why you can provide an empty array as second argument to the effect hook to avoid activating it on component updates but only for the mounting of the component.
Try this:
useEffect(async () => {
props.getCurrentOrders()
}, []);