I am using Formik in order to submit an array of components using MUI sliders.
I have created a slider component using the MUI library. You can see that in the code below in the declaration of:
import SliderSchedule from ....
So, I searched an example and I found a way to create and delete components and I copy from them. However now I want to also submit the result. But when I click the button I get no values.
As you can see I have the Comp1 that I declare the array const [sliderSchedule, setSliderSchedule]. Which has to contain values like: [(100, 200), (150, 300), (400, 700), ...].
Then I have the two function addHandeler and deleteHandeler that creates and deletes the components. This works fine.
Then we have the formik and that's the last thing that I have implemented after creating the the Comp2 that it's the "component" that we are creating with the addHandeler and deleteHandeler which creates the slider and a button to eliminate:
As you can see is very simple. And it works fine. But then when I click submit I get no values:
Thank you in advance.
import React from 'react';
import { useDispatch, useSelector } from "react-redux";
import history from "../../../history";
import { nanoid } from "nanoid";
/* MUI */
import { Container, Grid, Typography, Paper, TextField } from '#material-ui/core'
/* MUI edited Components */
import Appbar from '../../../components/Appbar';
import Button from '../../../components/Button';
import Translator from '../../../components/Translator';
import SliderSchedule from '../../../components/SliderSchedule';
/* Formik */
import { Formik, Form } from 'formik';
import * as Yup from "yup";
export default function Slots() {
const dispatch = useDispatch();
const paperStyle = { padding: 20, height: 'auto', width: 'auto', margin: "20px auto", backgroundColor: "#A9A9A9" }
function Comp2({ deleteHandeler, id, props }) {
return (
<Grid container item xs={12}>
<Grid item xs={11}> <SliderSchedule id={id} name={props.values.name} value={props.values.time} onChange={time => props.setFieldValue("time", time.target.value)} renderInput={(props) => <TextField {...props} />} /> </Grid>
<Grid item xs={1}> <Button type="button" style="Close" onClick={deleteHandeler}>CloseIcon</Button> </Grid>
</Grid>
);
}
const formSchema = {
time: []
};
function Comp1() {
const [sliderSchedule, setSliderSchedule] = React.useState([]);
const addHandeler = () => { setSliderSchedule(sliderSchedule => [...sliderSchedule, nanoid()]) };
const deleteHandeler = (removeId) => setSliderSchedule((sliderSchedule) => sliderSchedule.filter((id) => id !== removeId));
return (
<Formik
initialValues={formSchema}
onSubmit={values => {
console.log("Monday", values);
}}
render={props => (
<Form>
<Grid container justifyContent="center">
{sliderSchedule.map((id) => (<Comp2 key={id} id={id} deleteHandeler={() => deleteHandeler(id)} props={props} />))}
<Button variant="outlined" color="info" style="AddSlider" startIcon="AddIcon" onClick={addHandeler}> <Translator page="productSchedule" text="buttonAddSlider"></Translator> </Button>
<Button type="submit" variant="contained" color="primary"> Submit </Button>
</Grid>
</Form>
)}
/>
);
}
return (
<>
<Appbar></Appbar>
<Container>
<Grid container alignItems="flex-end">
{/* LA SUMA DE TOTS ELS xs={x} ha de ser xs={12} */}
<Grid container justifyContent="flex-start" item xs={12}>
<Typography variant="h3"> <Translator page="productSchedule" text="typographyTitle"></Translator> </Typography>
<Typography variant="h3"> 📅 </Typography>
</Grid>
<Grid item xs={12}>
<Paper elevation={10} style={paperStyle}>
<Grid container alignItems="flex-end">
<Grid container justifyContent="center" item xs="auto"> <Typography variant="h3"> <Translator page="productSchedule" text="typographyMonday"></Translator> </Typography> </Grid>
<Grid container justifyContent="center" item xs="auto"> <Comp1 /> </Grid>
</Grid>
</Paper>
</Grid>
</Grid>
</Container>
</>
);
}
Related
I am getting this error message in console (Uncaught TypeError: setCurrentId is not a function
at onClick (Post.js:19:1) )
I don't know how to handle this error
This is Child Component Post.js
import { Button, Card,CardActions,CardContent,CardMedia,Typography } from '#material-ui/core';
import React from 'react';
import useStyles from "./styles";
import MoreHorizIcon from '#mui/icons-material/MoreHoriz';
import DeleteIcon from '#mui/icons-material/Delete';
import ThumbUpAltIcon from '#mui/icons-material/ThumbUpAlt';
import moment from 'moment';
const Post= ({post , setCurrentId})=>{
const classes = useStyles();
return(
<Card className={classes.card}>
<CardMedia className={classes.media} image={post.selectedFile} title={post.title}/>
<div className={classes.overlay}>
<Typography variant='h6'>{post.creator}</Typography>
<Typography variant='body2'>{moment(post.createdAt).fromNow()}</Typography>
</div>
<div className={classes.overlay2}>
<Button style={{ color: 'white' }} size="small" onClick={() => setCurrentId(post._id)}><MoreHorizIcon fontSize="default" /></Button>
</div>
<div className={classes.details}>
<Typography variant='body2' color='textSecondary'>{post.tags.map((tag)=>`#${tag} `)}</Typography>
</div>
<CardContent>
<Typography className={classes.title} variant='h5' gutterBottom>{post.message}</Typography>
</CardContent>
<CardActions className={classes.cardActions}>
<Button size = 'small' color='primary' onClick={()=>{}}>
<ThumbUpAltIcon fontSize='small'/>
Like
{post.likeCount}
</Button>
<Button size = 'small' color='primary' onClick={()=>{}}>
<DeleteIcon fontSize='small'/>
Delete
</Button>
</CardActions>
</Card>
)
}
export default Post;
This is parent Component
import React from 'react';
import { Grid, CircularProgress } from '#material-ui/core';
import { useSelector } from 'react-redux';
import Post from './Post/Post';
import useStyles from './styles';
const Posts = ({ setCurrentId }) => {
const posts = useSelector((state) => state.posts);
const classes = useStyles();
return (
!posts.length ? <CircularProgress /> : (
<Grid className={classes.container} container alignItems="stretch" spacing={3}>
{posts.map((post) => (
<Grid key={post._id} item xs={12} sm={6} md={6}>
<Post post={post} setCurrentId={setCurrentId} />
</Grid>
))}
</Grid>
)
);
};
This is main file App.js
import React, { useState, useEffect } from 'react';
import { Container, AppBar, Typography, Grow, Grid } from '#material-ui/core';
import { useDispatch } from 'react-redux';
import Posts from './components/Posts/Posts';
import Form from './components/Form/Form';
import { getPosts } from './actions/posts';
import useStyles from './styles';
import memories from './images/memories.png';
const App = () => {
const [currentId, setCurrentId] = useState(0);
const dispatch = useDispatch();
const classes = useStyles();
useEffect(() => {
dispatch(getPosts());
}, [currentId, dispatch]);
return (
<Container maxWidth="lg">
<AppBar className={classes.appBar} position="static" color="inherit">
<Typography className={classes.heading} variant="h2" align="center">Memories</Typography>
<img className={classes.image} src={memories} alt="icon" height="60" />
</AppBar>
<Grow in>
<Container>
<Grid container justify="space-between" alignItems="stretch" spacing={3}>
<Grid item xs={12} sm={7}>
<Posts setCurrentId={setCurrentId} />
</Grid>
<Grid item xs={12} sm={4}>
<Form currentId={currentId} setCurrentId={setCurrentId} />
</Grid>
</Grid>
</Container>
</Grow>
</Container>
);
};
export default App;
I am trying to debug my react code and expecting something that I missed
I have multiple grids showing information, but I thought it would be neat to have the end user click on one of the grids and expands it to view larger. Maybe adding a button on each grid to expand it, but is there a way to just click on the grid to maximize and then minimize.
import React from 'react';
import Box from '#mui/material/Box';
import Grid from '#mui/material/Grid';
import Radio from '#mui/material/Radio';
import Typography from '#mui/material/Typography';
import RadioGroup from '#mui/material/RadioGroup';
import FormControlLabel from '#mui/material/FormControlLabel';
import FormControl from '#mui/material/FormControl';
import FormLabel from '#mui/material/FormLabel';
import { TrendLine, Gauge, InfoCard } from '#backstage/core-components';
const PeriodSelector = (children?: React.ReactNode):JSX.Element | null => {
return (
<FormControl >
<FormLabel id="period" title="Trends">Trend Period</FormLabel>
<RadioGroup
row
aria-labelledby="period"
name="period-radio-buttons-group"
>
<FormControlLabel value="today" control={<Radio />} label="today" />
<FormControlLabel value="week" control={<Radio />} label="week" />
<FormControlLabel value="month" control={<Radio />} label="month" />
<FormControlLabel value="year" control={<Radio />} label="year" />
</RadioGroup>
</FormControl>
);
}
// They do not export InfoCard.Props up through the modules.
const StatsInfoCard = (props?:any):JSX.Element | null => {
return (
<InfoCard variant={"fullHeight"} title={props.title} titleTypographyProps={{variant: 'p'}}>
{props.children}
</InfoCard>
);
}
// Again they do not export props from their libraries which is a pain for extensibility and
// typescript safety so I anonymize it.
const StatsTrendCard = (props?:any):JSX.Element | null => {
return (
<StatsInfoCard title={props.title}>
<TrendLine
data={props.data}
color={props.color}
title={props.title} >
</TrendLine>
</StatsInfoCard>
);
}
const StatsGaugeCard = (props?:any):JSX.Element | null => {
return (
<StatsInfoCard title={props.title}>
<Gauge getColor={ () => { return props.color} } fractional={false} {...props} />
</StatsInfoCard>
);
}
const TotalCard = (props?:any):JSX.Element | null => {
return (
<StatsInfoCard {...props} >
<Typography variant="h2" align="center" {...props}>
{props.value}
</Typography>
</StatsInfoCard>
);
}
export function analysisgrids() {
return (
<Box sx={{ flexGrow: 1 }}>
<Grid container spacing={2}>
<Grid item xs={12}>
<div align="center">
<PeriodSelector />
</div>
</Grid>
<Grid item xs={3}>
<StatsTrendCard
data={[0.1, 0.5, 0.9, 1.0]}
color="red"
title="Average build execution time" />
</Grid>
<Grid item xs={3}>
<StatsTrendCard
data={[0.1, 0.5, 0.9, 1.0]}
color="green"
title="Green Builds per day trend" />
</Grid>
<Grid item xs={3}>
<StatsTrendCard
data={[0.1, 0.5, 0.9, 1.0]}
color="black"
title="Total Builds per day trend" />
</Grid>
<Grid item xs={3}>
<StatsTrendCard
data={[0.1, 0.5, 0.9, 1.0]}
color="purple"
title="Total Active Branches" />
</Grid>
<Grid item xs={3}>
<TotalCard title="Total builds" value="234" color="green" unit="" />
</Grid>
<Grid item xs={3}>
<TotalCard title="Broken build recover time" value="1" unit="hrs" color="purple"/>
</Grid>
<Grid item xs={3}>
<StatsGaugeCard title="% failed builds" value="50" color="red"/>
</Grid>
<Grid item xs={3}>
<TotalCard title="Avg Test Execution time" value="21" unit="minutes" color="blue"/>
</Grid>
</Grid>
</Box>
);
}
export default {
title: 'demos/staticanalysis',
component: analysisgrids,
};
I did some digging around material ui page and couldn't find a specific justification on.
i am getting the below error
TypeError: Cannot read properties of undefined (reading 'name') in react
data is not coming from the Products.
i am learning the react now and this is my first project so could you please help to sort out this issue.
index.js
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById("root")
);
App.js
import React from "react";
import Products from "./Components/Products/Products";
const App = () => {
return (
<div>
<Products />
</div>
);
};
export default App;
Products.jsx
import React from "react";
import { Grid } from "#material-ui/core";
import Product from "./Product/Product";
const products = [
{
id: 1,
name: "Macbook Air",
description: "Apple Macbook Air",
price: "$999",
},
{
id: 2,
name: "Macbook Pro",
description: "Apple Macbook Pro",
price: "$1199",
},
];
const Products = () => {
return (
<main>
<Grid container justify="center" spacing={4}>
{products.map((product) => (
<Grid item key={product.id} xs={12} sm={6} md={4} lg={3}>
<Product />
</Grid>
))}
</Grid>
</main>
);
};
export default Products;
Product.jsx
import React from "react";
import {
Card,
CardMedia,
CardContent,
CardActions,
Typography,
IconButton,
} from "#material-ui/core";
import { AddShoppingCart } from "#material-ui/icons";
import useStyles from "./styles";
const Product = ({ product }) => {
const classes = useStyles();
return (
<Card className={classes.root}>
<CardMedia className={classes.media} image="" title={product.name} />
<CardContent>
<div className={classes.cardContent}>
<Typography variant="h5" gutterBottom>
{product.name}
</Typography>
<Typography variant="h5">{product.price}</Typography>
</div>
<Typography variant="h2" color="textSecondary">
{product.description}
</Typography>
</CardContent>
<CardActions disableSpacing className={classes.cardActions}>
<IconButton aria-label="Add to cart">
<AddShoppingCart />
</IconButton>
</CardActions>
</Card>
);
};
export default Product;
How can i solve the above problem
For reference please find the attached image
You didn't pass the product prop to your <Product/> component, so it's undefined by default, and then you're referencing the property name in the Product component of an undefined prop, therefore you get the error.
Make the following change
const Products = () => {
return (
<main>
<Grid container justify="center" spacing={4}>
{products.map((product) => (
<Grid item key={product.id} xs={12} sm={6} md={4} lg={3}>
<Product product={product}/>
</Grid>
))}
</Grid>
</main>
);
};
It appears you are not passing the product as a prop to you <Product /> component.
Add this to your map:
{products.map((product) => (
<Grid item key={product.id} xs={12} sm={6} md={4} lg={3}>
<Product product={product}/>
</Grid>
))}
need to pass prop to your component
{products.map((product) => (
<Grid item key={product.id} xs={12} sm={6} md={4} lg={3}>
<Product product={product}/>
</Grid>
))}
Here is my code.
My goal is: when I click on Login button, content will show the Login card and when I click on Register button content will show the Register card.
As for my primary test, I used the following code:
import React,{useState} from 'react'
const Login=()=>{
return(
<form>
<label>Username:</label>
<input type="text" value="username"/>
<label>Password:</label>
<input type="password" value="password"/>
<button>Submit</button>
</form>
)
}
const Register=()=>{
return(
<form>
<label>Name:</label>
<input type="text" value="name"/>
<label>Username:</label>
<input type="text" value="username"/>
<label>Password:</label>
<input type="password" value="password"/>
<button>Register</button>
</form>
)
}
export default function App() {
const [click,setClick]=useState(false)
const handleClick=()=>{
setClick(true)
}
return (
<div>
<button onClick={handleClick}>Login</button>
{click?<Login/>:<Register/>}
</div>
)
}
And it works. In this way I tried to render functionalities in different components. It seems like not working. What am I missing here?
The following corrections will help you:-
You need to make App component responsible for maintaining click state and then pass only handler (setClick) to AppBar and only state (click) to Content.
import React, { useState } from "react";
import Login from "./Login";
import Register from "./Register";
import { makeStyles } from "#material-ui/core/styles";
import AppBar from "#material-ui/core/AppBar";
import Toolbar from "#material-ui/core/Toolbar";
import Typography from "#material-ui/core/Typography";
import Button from "#material-ui/core/Button";
import IconButton from "#material-ui/core/IconButton";
import MenuIcon from "#material-ui/icons/Menu";
import { Grid } from "#material-ui/core";
const useStyles = makeStyles(theme => ({
root: {
flexGrow: 1
},
menuButton: {
marginRight: theme.spacing(2)
},
title: {
flexGrow: 1
}
}));
function Appbar({ handleClick }) {
const classes = useStyles();
return (
<div className={classes.root}>
<AppBar position="static">
<Toolbar>
<IconButton
edge="start"
className={classes.menuButton}
color="inherit"
aria-label="menu"
>
<MenuIcon />
</IconButton>
<Typography variant="h6" className={classes.title}>
ReactApp
</Typography>
<Button color="inherit" onClick={()=>handleClick(true)}>
Login
</Button>
<Button color="inherit" onClick={()=>handleClick(false)}>
Register
</Button>
</Toolbar>
</AppBar>
</div>
);
}
function Content({ click }) {
const classes = useStyles();
return (
<div className={classes.root}>
<Grid container style={{ padding: 80 }} item>
<Grid xs={false} sm={4} />
<Grid xs={12} sm={8} />
{click ? (
<Login onClick={handleClick} />
) : (
<Register onClick={handleClick} />
)}
<Grid />
<Grid xs={false} sm={2} />
</Grid>
</div>
);
}
export default function App() {
const [click, setClick] = useState(true);
const handleClick = (value) => {
setClick(value);
};
return (
<div>
<Appbar handleClick={handleClick} />
<Content click={click} />
</div>
);
}
I get this error when trying to submit a Formik form.
Warning: Can't perform a React state update on an unmounted component.
This is a no-op, but it indicates a memory leak in your application.
To fix, cancel all subscriptions and asynchronous tasks in a useEffect
cleanup function.
in Formik (at layout.tsx:113)
in div (created by ForwardRef(CardContent))
in ForwardRef(CardContent) (created by WithStyles(ForwardRef(CardContent)))
in WithStyles(ForwardRef(CardContent)) (created by Context.Consumer)
in StyledComponent (created by Styled(WithStyles(ForwardRef(CardContent))))
in Styled(WithStyles(ForwardRef(CardContent))) (created by CardContent)
in CardContent (created by Context.Consumer)
in StyledComponent (created by Styled(CardContent))
in Styled(CardContent) (at layout.tsx:112)
in div (created by ForwardRef(Paper))
in ForwardRef(Paper) (created by WithStyles(ForwardRef(Paper)))
in WithStyles(ForwardRef(Paper)) (created by ForwardRef(Card))
in ForwardRef(Card) (created by WithStyles(ForwardRef(Card)))
in WithStyles(ForwardRef(Card)) (created by Context.Consumer)
in StyledComponent (created by Styled(WithStyles(ForwardRef(Card))))
in Styled(WithStyles(ForwardRef(Card))) (created by Card)
in Card (at layout.tsx:111)
The function onSubmit has no async calls:
<Formik
...
onSubmit={(values, { setSubmitting }): void => {
setTimeout(() => {
// convert daysOfWeek to Weekday[]
const daysOfWeek = values.daysOfWeek
.filter(day => day.checked)
.map(day => day.dayOfWeek)
const edited: EditTask = { ...task, ...values, daysOfWeek }
onEditTask(edited)
setSubmitting(false)
})
}}
>
The onEditTask callback just updates the list of TaskItems.
The full TaskItem component looks like this. The '#web/core...' components are my own wrappers around Material UI components.
TaskItem.tsx
import React, { ReactElement } from 'react'
import { useTranslation } from 'react-i18next'
import Grid from '#material-ui/core/Grid'
import ListItemIcon from '#material-ui/core/ListItemIcon'
import ListItemText from '#material-ui/core/ListItemText'
import CloseIcon from '#material-ui/icons/Close'
import Typography from '#web/core/components/Typography'
import MenuButton from '#web/core/components/MenuButton'
import MenuItem from '#web/core/components/MenuItem'
import TextField from '#web/core/components/TextField'
import Checkbox from '#web/core/components/Checkbox'
import Button from '#web/core/components/Button'
import Card from '#web/core/components/Card'
import EditIcon from '#web/core/theme/icons/Edit'
import { TaskSchedule, Weekday } from 'stores/goals/models'
import {
EditTask,
getDistinctTaskSchedulesSorted,
} from 'components/CitizenDetails/DietRules/FormDrawer'
import { TaskItemViewMode } from 'components/CitizenDetails/DietRules/TaskItem'
import { Formik, FieldArray, Form } from 'formik'
import uuid from 'uuid/v4'
import * as Yup from 'yup'
import TaskOverview from '../TaskOverview'
import { DeleteIcon, DeleteMenuItemText, EditCardContent, RemoveScheduleButton } from './styled'
const taskValidationSchema = Yup.object().shape({
subject: Yup.string().required('Required'),
description: Yup.string().nullable(),
daysOfWeek: Yup.array()
.min(1, 'Min 1 day')
.required('Required'),
taskSchedules: Yup.array()
.ensure()
.min(0, 'Min 0 elements'),
})
interface Props {
viewMode: TaskItemViewMode
task: EditTask
onChangeViewMode: (viewMode: TaskItemViewMode) => void
onDeleteTask: () => void
onEditTask: (task: EditTask) => void
disableMenu?: boolean
}
export interface CheckedWeekday {
checked: boolean
dayOfWeek: Weekday
}
function mapToCheckedWeekday(weekday: Weekday, checked: boolean): CheckedWeekday {
return {
dayOfWeek: weekday,
checked,
}
}
export default function TaskItem({
viewMode,
task,
onChangeViewMode,
onDeleteTask,
onEditTask,
disableMenu,
}: Props): ReactElement {
const [t] = useTranslation()
type TaskFormValues = Pick<EditTask, 'subject' | 'description'> & {
daysOfWeek: CheckedWeekday[]
taskSchedules: TaskSchedule[]
}
const initialValues: TaskFormValues = {
...task,
daysOfWeek: Object.values(Weekday).map(day =>
mapToCheckedWeekday(day, task.daysOfWeek.includes(day))
),
taskSchedules: getDistinctTaskSchedulesSorted(task.taskSchedules),
}
return (
<>
{viewMode === TaskItemViewMode.View ? (
<Grid container justify="space-between" alignItems="center">
<Grid item>
<TaskOverview task={task} />
</Grid>
<Grid item>
{!disableMenu && (
<MenuButton id="diet-task-overview-menu-button">
<MenuItem onClick={(): void => onChangeViewMode(TaskItemViewMode.Edit)}>
<ListItemIcon>
<EditIcon />
</ListItemIcon>
<ListItemText primary={t('edit')} />
</MenuItem>
<MenuItem key="diet-task-overview-menu-remove-button" onClick={onDeleteTask}>
<ListItemIcon>
<DeleteIcon />
</ListItemIcon>
<DeleteMenuItemText primary={t('remove')} />
</MenuItem>
</MenuButton>
)}
</Grid>
</Grid>
) : (
<Card>
<EditCardContent>
<Formik
initialValues={initialValues}
validationSchema={taskValidationSchema}
onSubmit={(values, { setSubmitting }): void => {
setTimeout(() => {
// convert daysOfWeek to Weekday[]
const daysOfWeek = values.daysOfWeek
.filter(day => day.checked)
.map(day => day.dayOfWeek)
const edited: EditTask = { ...task, ...values, daysOfWeek }
onEditTask(edited)
setSubmitting(false)
})
}}
>
{({
values,
errors,
isValid,
touched,
dirty,
handleChange,
handleBlur,
handleSubmit,
handleReset,
isSubmitting,
validateForm,
}): ReactElement => (
<Form>
<Grid container direction="column" spacing={3}>
<Grid item>
<Typography variant="h6">{t('goals:diet.task.title')}</Typography>
</Grid>
<Grid item>
<TextField
id={`task-${task.uuid}-subject`}
label={t('title')}
name="subject"
onChange={handleChange}
onBlur={handleBlur}
value={values.subject}
fullWidth
inputProps={{ autoFocus: viewMode === TaskItemViewMode.Create }}
/>
{errors.subject && touched.subject && errors.subject}
</Grid>
<Grid item>
<TextField
id={`task-${task.uuid}-description`}
label={t('description')}
name="description"
onChange={handleChange}
onBlur={handleBlur}
value={values.description}
rows="3"
multiline
fullWidth
/>
</Grid>
<Grid item>
<Typography variant="subtitle1" gutterBottom>
{t('day').toUpperCase()}
</Typography>
<FieldArray
name="daysOfWeek"
render={({ replace }) => (
<Grid container spacing={2}>
{values.daysOfWeek.map((day, idx) => (
<Grid item key={`task-weekday-${day.dayOfWeek}`}>
<Checkbox
id={`task-weekday-checkbox-${day.dayOfWeek}`}
name={`daysOfWeek.${idx}.dayOfWeek`}
value={day.dayOfWeek}
checked={day.checked}
label={t(`weekdays.${day.dayOfWeek.toLowerCase()}`, {
context: 'short',
})}
onChange={e => {
replace(idx, { ...day, checked: !day.checked })
}}
/>
</Grid>
))}
</Grid>
)}
/>
</Grid>
<FieldArray
name="taskSchedules"
render={({ remove, replace, push }) => (
<>
<Grid item>
<Typography variant="subtitle1" gutterBottom>
{t('schedule_plural').toUpperCase()}
</Typography>
{values.taskSchedules.map((schedule, idx) => (
<Grid
container
spacing={6}
key={`task-weekday-schedule-${schedule.uuid}`}
>
<Grid item>
<TextField
type="time"
key={`task-schedule-${schedule.uuid}`}
id={`task-schedule-${schedule.uuid}`}
label={t('time')}
name={`taskSchedules.${idx}.time`}
value={schedule.time}
onChange={e => {
const time = e.target.value
replace(idx, { ...schedule, time })
}}
inputProps={{
step: 300, // 5 min
}}
/>
</Grid>
<Grid item>
<RemoveScheduleButton
id={`task-weekday-button-remove-schedule-${schedule.uuid}`}
vanilla
icon
onClick={(): void => {
remove(idx)
// bug in formik makes this necessary
// see https://github.com/jaredpalmer/formik/issues/784#issuecomment-503135849
setTimeout(() => {
validateForm()
}, 10)
}}
>
<CloseIcon />
</RemoveScheduleButton>
</Grid>
</Grid>
))}
</Grid>
<Grid item>
<Button
id="task-weekday-button-add-schedule"
ghost
onClick={(): void => {
push({
time: '00:00:00',
taskUuid: task.uuid,
uuid: uuid(),
dayOfWeek: Weekday.Monday, // temporary value
})
}}
>
{t('goals:diet.task.add-schedule')}
</Button>
</Grid>
</>
)}
/>
<Grid item>
<Grid container justify="flex-end" spacing={2}>
<Grid item>
<Button
id="task-button-cancel-editing"
size="small"
ghost
licorice
onClick={
viewMode === TaskItemViewMode.Create
? onDeleteTask
: (): void => {
handleReset()
onChangeViewMode(TaskItemViewMode.View)
}
}
>
{t('cancel')}
</Button>
</Grid>
<Grid item>
<Button
type="submit"
id="task-button-save-editing"
size="small"
disabled={!dirty || !isValid || isSubmitting}
>
{t('ok')}
</Button>
</Grid>
</Grid>
</Grid>
</Grid>
</Form>
)}
</Formik>
</EditCardContent>
</Card>
)}
</>
)
}
Probably onEditTask is changing the viewMode, removing the <EditCardContent>, so when the call to setSubmitting happens Formik is already unmounted.