how to loop a swal on cancel click? (react.js) - javascript

I want to keep popping up a swal in each time the swal is closed rather then giving okay.
swal({
content: (
<Box>
<Typography variant="h4">Ready? </Typography>
</Box>
),
buttons: ["Nooo!", "okay"],
}).then((value2) => {
if (value2) {
swal({
content: (
<Box>
<Typography variant="h4">
Ready now?
</Typography>
</Box>
),
})
}
})
I want to give the swal of "Are you ready now?" whenever "NO" is clicked. only close the swal on "okay " clicked. How can I create this loop?

Related

Custom Pagination in Material-Table

I want to override the default pagination in Material-Table to look different, but keep the same default elements there. My override allows me to move between pages in the table, but I cannot change how many rows appear in the table. I cannot skip to the last or first page either. I want to keep the exact same options as what is there by default, but change how they look.
All of my Icon, Grid, Typography, etc, imports are #material-ui/core/ or #material-ui/icons/
function IntakeList() {
const CustomPaginationComponent = (props) => {
const { page, rowsPerPage, count, onChangePage } = props;
let from = rowsPerPage * page + 1;
let to = rowsPerPage * (page + 1);
if (to > count) {
to = count;
}
return (
<td>
<Grid container alignItems="center" style={{ paddingTop: 8 }}>
<Grid item>
<IconButton disabled={page === 0} onClick={(e) => onChangePage(e, page - 1)}>
<SkipPreviousIcon fontSize="small" color={page === 0 ? "disabled" : "primary"} />
<Typography>Prev</Typography>
</IconButton>
</Grid>
<Grid item>
<Typography variant="caption" style={{ color: "black" }}>
{from}-{to} of {count}
</Typography>
</Grid>
<Grid item>
<IconButton disabled={to >= count} onClick={(e) => onChangePage(e, page + 1)}>
<Typography>Next</Typography>
<SkipNextIcon fontSize="small" color={to < count ? "primary" : "disabled"} />
</IconButton>
</Grid>
</Grid>
</td>
);
};
return (
<MaterialTable
title="Title"
data={data}
columns={columns}
options={{
pageSize: 10,
pageSizeOptions: [10, 15, 25, 50, 100],
}}
components={{
Pagination: (props) => {
return <CustomPaginationComponent {...props} />;
},
}}
/>
);
}
What you have done so far is right. You just simply have to code for the "skip to last page", "skip to first page" and "select row options" just like you did for "next" and "previous" page.
https://codesandbox.io/s/solution-q1cmer?file=/src/App.js
When you console log the props of pagination you will get this
Using the rowsPerPageOptions , onChangeRowsPerPage and some of the code you have coded I was able to code the number of rows per page.
To be honest I don't think you have to code to next page and previous page functionality. It's already in props. You simply has to declare them in the right place.
Happy Coding

Having Issues with Components Not Rendering or Re-Rendering Too Many Times on State Change

We're working on an inventory management page of sorts. The page makes a call to an external API and if that endpoint returns data, it displays that data on the page for the user. The API call uses the current logged in users ID, so we use userLoaded to wait for that ID before making the API call.
If an inventory doesn't exist (API returns nothing), we show some "Not Available" text.
However, when a page initially loads, it's showing the "Not Available" text, re-rendering a couple times, and then finally showing the correct data. Is there anyway to cut back on those re-renders or make it more graceful?
You can see the issue here: https://recordit.co/EYDLupg3xs or on the demo link here: https://showzone.io/inventory
Oddly enough, the table component is not re-rendering with the data - so it stays blank. But if you force the table to re-render (by using one of the Filters for example), the data does indeed show. How can we re-render the table component when the data is ready?
Here is the code (cut down a bit to make it easier to understand):
function Inventory() {
const { currentUser, userLoaded } = useAuth()
const [data, setData] = useState([])
const [inventoryExists, setInventoryExists] = useState(false)
const fetchData = useCallback(async () => {
if (userLoaded) {
const userInventoryData = await axios.get(
`https://showzone-api.herokuapp.com/api/user-inventory/${currentUser.uid}` // For the demo link, I hardcoded a value for testing purposes
)
setData(userInventoryData.data)
setInventoryExists(true)
}
}, [currentUser?.uid, userLoaded])
useEffect(fetchData, [fetchData])
return (
<>
.....
<TabPanel value="1" sx={{ padding: 0 }}>
<Card mb={6}>
<CardContent>
<Grid container spacing={6}>
<Grid item xs={12}>
<Typography>
<strong>Total Cards: </strong>{" "}
{inventoryExists
? data?.owned_count?.toLocaleString() +
" / " +
data?.total_card_count?.toLocaleString()
: "Not Available"}
</Typography>
<Typography>
<strong>Estimated Value: </strong>{" "}
{inventoryExists
? data?.owned_value?.toLocaleString()
: "Not Available"}
</Typography>
</Grid>
<Grid item xs={12} md={6} sx={{ display: "flex" }}>
{inventoryExists ? (
<div>
<Doughnut
data={{
datasets: [
{
data: [
Math.round(data?.owned_count),
Math.round(data?.total_card_count),
],
},
],
}}
/>
</div>
) : (
<BlankDoughnut text="Cards" />
)}
</Grid>
</Grid>
</CardContent>
</Card>
</TabPanel>
<Divider />
{inventoryExists ? (
<PlayerSearch id={currentUser?.uid} />
) : (
<PlayerSearch />
)}
</>
)
}

React Hook useState value being reset to initial value

The state of a value set using React useState hook gets set to the proper value and then reset to null. Critical code below. The click event that sets the startDate to the current date and time is 3 components down from where startDate is initialized. When setStartDate did not work I created an arrow function, updateStartDate. Both had the same problem where the startDate was changed after the click event (witnessed per the console.log in the top component), but was null just before the next click event (per the console.log in the click event). This is not an async problem as I see the change made before subsequent click.
If this is something that just does not work please explain. I could probably fix with useReducer but prefer to keep the useState if there is something I can do to correct this... If not correctable then I would like to at least understand why it does not work so that I can avoid this problem in the future.
export const DisplayTicTacToeContainer = (props) => {
const [startDate, setStartDate]= useState();
const updateStartDate = (newDate) => {
setStartDate(newDate);
}
useEffect (() => {
setStartDate(null);
}, []);
useEffect(() => {
console.log( "displayTicTacToeContainer useEffect for change of startDate = ", startDate)
}, [startDate]);
return (
<DisplayTicTacToeMatch arrayOfMatchingItems ={arrayOfMatchingItems}
startDate={startDate}
setStartDate={setStartDate}
updateStartDate={updateStartDate}
/>);
}
//-----------------------------------------------
export const DisplayTicTacToeMatch = (props) => {
const { startDate,
setStartDate,
updateStartDate,
} = props;
useEffect(() => {
// Performs some prep and working fine.
}, []);
return (
<TicTacToe
startDate={startDate}
setStartDate={setStartDate}
updateStartDate={updateStartDate}
/>
);
}
//-----------------------------------------------
const TicTacToeContainer = (props) => {
const { startDate,
setStartDate,
updateStartDate,
} = props;
const [board, setBoard] = useState(<Board
updateStartDate={updateStartDate}
startDate={startDate}
setStartDate={setStartDate}/>);
return (
<Board/>
)
}
export default TicTacToeContainer;
I renamed the component to BoardComponent and the state variable to boardLayout. I included the full return portion of the BoardComponent below.
As I am still experiencing the problem I would agree with you that, "DisplayTicTacToeContainer is being mounted twice". Any thoughts on how I can avoid this from happening?
Other than this inability to setStartDate, everything is working fine.
//-----------------------------------------------
const Board = (props) => {
const { updateStartDate,
startDate,
setStartDate,
} = props;
return (
<>
<Grid container maxwidth="lg" alignItems="center" spacing={1}>
<Grid item xs={9}>
<Grid container alignItems="center">
<Grid item xs={9}>
<Typography variant = "body1">
First select a square. Once the "Inquiry" word or phrase appears below, find
the correct response in the column on the right and select that buttton. A correct
response will fill the square previously selected with an "O" or "X".
</Typography>
<div style={{ width: '100%' }}>
<Box
display="flex"
flexWrap="wrap"
p={1}
m={1}
bgcolor="background.paper"
css={{ maxWidth: 900 }}
>
<Box p={1} bgcolor="grey.300">
Inquiry : {inquiry}
</Box>
</Box>
<Box
display="flex"
flexWrap="wrap"
p={1}
m={1}
bgcolor="background.paper"
css={{ maxWidth: 900 }}
>
<Box p={1} bgcolor="grey.300">
Next move by : {currentPlayer}
</Box>
<Box p={1} bgcolor="grey.300">
{showStatus}
</Box>
</Box>
</div>
</Grid>
</Grid>
<MyAux>
{boardLayout.map((row, rowId) => {
const columns = row.map((column, columnId) => (
<Grid key={columnId} item>
<ButtonBase >
<Paper
onClick={(e) => {
clickSquareHandler(e);
}}
elevation={4}
data-coord={rowId + ':' + columnId}
id={"Square" + rowId.toString() + columnId.toString()}
className={classes.Paper}>
<Icon
className={classes.Icon}
style={{fontSize: 78}}>
</Icon>
</Paper>
</ButtonBase>
</Grid>
));
return (
<Grid
key={rowId}
className={classes.Grid}
container
spacing={2}>
{columns}
</Grid>)
})}
</MyAux>
</Grid>
<Grid item xs={3} >
<Paper className={classes.paper}>
<Typography variant = "body1">
Response Options
</Typography>
<ButtonGroup
orientation="vertical"
color="secondary"
aria-label="vertical outlined secondary button group"
>
{responseChoices.map((choice) => (
<Controls.Button
key ={choice.value}
text={choice.value}
variant="contained"
color = "secondary"
onClick={() => {
chooseChecker(choice);
}}
className={
response && response.value === choice.value ? "selected" : ""
}
disabled={!!selected[choice.value]}
fullWidth = "true"
size = "small"
/>
))}
</ButtonGroup>
</Paper>
</Grid>
</Grid>
</>
)
}
BoardContainer.propTypes = {
won: PropTypes.func,
size: PropTypes.number
};
export default BoardContainer;
At least, code below doesn't make much sense.
Please don't set state value as a component.
Also, try to name state variable different from components, since it will confuse you at some ppint.
const [board, setBoard] = useState(<Board
updateStartDate={updateStartDate}
startDate={startDate}
setStartDate={setStartDate}/>);
return (
<Board/>
)
Another possibility is that the DisplayTicTacToeContainer is being mounted twice, but I can't confirm it with the code provided.

Material-ui Dialog: manipulating the Escape button and mouse clicking outside of the dialog

I'm using material-ui's dialog: when a user presses "sign out" button, a dialog opens and there appears "yes" or "no" buttons asking whether the user realy wants to sign out or not.
When the user clicks the "escape" button or just clicks outside of the window, it signs him out - as if he pressed "yes". How can I control this? I want those to activate the "no" button.
Thanks!
Ciao, you could use a Confirmation Dialog variant of Mui Dialog. In this way you could force the user to click button Yes or No in your dialog.
Here I made a codesandbox example (inspired by Mui Dialog page)
Basically I made a simple Button with a component that calls Dialog:
return (
<div className={classes.root}>
<Button onClick={handleClickListItem}>sign out</Button>
<ConfirmationDialogRaw
classes={{
paper: classes.paper
}}
keepMounted
open={open}
onClose={handleClose}
/>
</div>
);
The ConfirmationDialogRaw component:
function ConfirmationDialogRaw(props) {
const { onClose, open, ...other } = props;
const handleCancel = () => {
// here just close the confirmation dialog
console.log("stay in");
onClose();
};
const handleOk = () => {
// here manage signout
console.log("sing out");
onClose();
};
return (
<Dialog
disableBackdropClick
disableEscapeKeyDown
maxWidth="xs"
aria-labelledby="confirmation-dialog-title"
open={open}
{...other}
>
<DialogTitle id="confirmation-dialog-title">Sing Out</DialogTitle>
<DialogContent dividers>
<Typography>Are you sure you want to exit?</Typography>
</DialogContent>
<DialogActions>
<Button autoFocus onClick={handleCancel} color="primary">
No
</Button>
<Button onClick={handleOk} color="primary">
Yes
</Button>
</DialogActions>
</Dialog>
);
}
The magic is done by props disableBackdropClick and disableEscapeKeyDown on Dialog component.

Material-ui close all other card content when clicking one

I would like to close all other opened cards while I click another one, I would want something that works like Accordion Component.
My current code looks as below:
<List>
{
this.results.map((result: PTemplate, index: number) => {
return (
<ResultCard key={"row_"+index} result={result} id={index} initiallyExpanded={false}></ResultCard>
)
})
}
</List>
looks smth like this:
<Card key={'res_'+result.id} initiallyExpanded={initiallyExpanded} style={styles.resultInstance}>
<CardHeader actAsExpander={true} showExpandableButton={true} style={resultTypeStyle}>
<Flexbox>Header</Flexbox>
</CardHeader>
<CardText actAsExpander={false} expandable={true} key={'res_cont_'+result.id}>Description here</CardText>
</Card>
Any idea how would I do this?

Categories