how to delete the formik values using field array - reactjs

how can we delete the formik values when using field arrays .So Its gets
deleted from the UI when I delete it , but stays in the formik values.
can I edit/modify formik values directly ?
I am new to react here. Thanks
{
Client:
Phone: [
{
PhoneNumber:"",
PhoneType:""
}
]
}
I am able to delete the occurrence from the state, but formik values still retains the values.
const Phone = ({ title, binding }) => {
const [phones, setPhones] = useState([])
return (
<Fragment>
<Grid item xs={12} md={6}>
<SectionField
title={title}
name={binding + `.Phone.PhoneNumber`}
required
label="Phone"
fullWidth
type="tel"
component={TextField}
/>
</Grid>
<Grid item xs={12} sm={3}>
<SectionField
title={title}
name={binding + `.Phone.PhoneType`}
required
defaultValue={{ label: "", value: "" }}
label="Phone Type"
suggestions={phoneTypes}
component={MuiReactSelect}
/>
</Grid>
<IconButton onClick={() => {
setPhones(currentValue => [...currentValue, {
id: generate(),
PhoneNumber: "",
PhoneType: ""
}])
}}>
<AddBoxIcon fontSize="large" />
</IconButton>
{phones.map((p, index) => (
<Fragment key={p.id}>
<Grid item xs={12} md={5}>
<SectionField
title={title}
name={binding + `.Phone[${index}].PhoneNumber`}
required
label="Phone"
fullWidth
type="tel"
component={TextField}
/>
<ErrorMessage name={`Client.Phone.${index}.PhoneNumber`} /><br />
</Grid>
<Grid item xs={12} sm={3}>
<SectionField
title={title}
name={binding + `.Phone[${index}].PhoneType`}
required
defaultValue={{ label: "", value: "" }}
label="Phone Type"
suggestions={phoneTypes}
component={MuiReactSelect}
/>
</Grid>
<IconButton onClick={() => {
setPhones(currentPhone =>
currentPhone.filter(x => x.id !== p.id))
}}>
<RemoveCircleIcon fontSize="large" />
</IconButton>
</Fragment>
))}
</Fragment>
)
};export default Phone;
Formik values:
======================================================
"Phone": {
"0": {
"PhoneNumber": "8578882942",
"PhoneType": "Home"
},
"PhoneNumber": "8578882942",
"PhoneType": "Home"
},

I got into same sort of inconvenience when i wanted to delete that element from Ui but its values in formik stays there.
What i did was use formik's setFieldValue: (field: string, value: any, shouldValidate?: boolean) => void
So lets say you are using a button to remove that element from UI so i added an extra something to it like this to its onClick property :
//formik.setFieldValue({name of the element that you want to delete})
onClick = {()=>{
//whatever work you need to do for removing it from ui
//then
//formik.setFieldValue({name of the element that you want to delete})
formik.setFieldValue(index)
// here index was the name of variable that i used for that element
}}
Then in the formik's useFormik() hook i did something like this:
const formik = useFormik({
initialValues: {
//your initial values
},
onSubmit: (values) => {
// your onSubmit
},
setFieldValue: (field) => {
delete values.field;
},
});
Sorry i know that this answer is late but i hope it would help someone

Related

Dynamically adding or removing items within a react-hook-forms form and registering the inputs?

I'm trying to implement a rather complicated form that has and date picker and input which the user can add multiple of (or delete). That data then gets added to the overall form on submit. How do I get react-hook-forms to register that little dynamic faux form within the real form?
Here's the faux form inputs:
<AddPackagesStyle>
<Label htmlFor="addedPackages" label="Add Packages" />
<DatePicker
id="dateRange"
selected={startDate}
selectsRange
startDate={startDate}
endDate={endDate}
placeholderText="select dates"
onChange={onDateChange}
/>
<PackageInput
id="PackageSelect"
placeholder="Select Package"
type="text"
value={name}
// #ts-ignore
onChange={(e) =>
// #ts-ignore
setName(e.target.value)
}
/>
<ButtonContainer>
<button type="button" onClick={clearAll}>
Clear
</button>
<button
type="button"
// #ts-ignore
onClick={addPackage}
>
Add
</button>
</ButtonContainer>
</AddPackagesStyle>
These entries get added to an array in a useState hook:
const [addedPackages, setAddedPackages] = useState<any[]>([])
Then this gets rendered in JSX as the add packages:
<ContentSubscriptionWrapper>
{addedPackages.length !== 0 &&
addedPackages.map((addedPackage, idx) => (
// #ts-ignore
<>
<ContentSubscriptionColumn>
{addedPackage.name && addedPackage.name}
</ContentSubscriptionColumn>
<ContentSubscriptionColumn>
{addedPackage.startDate &&
addedPackage.startDate.toString()}
</ContentSubscriptionColumn>
<ContentSubscriptionColumn>
{addedPackage.endDate && addedPackage.endDate.toString()}
</ContentSubscriptionColumn>
<button type="button" onClick={() => removePackage(idx)}>
X
</button>
</>
))}
</ContentSubscriptionWrapper>
So before the form gets submitted, the 'add packages' has to be set. Where do I add the {...register} object to add to the larger form object for submission?
const {
control,
register,
handleSubmit,
formState: { errors },
} = useForm<any>()
const onSubmit = (data: any) => {
console.log(data)
}
I created a CodeSandbox trying to reproduce your use case and used Material UI to get it done quickly, but you should get the idea and can modify it with your own components.
you should let RHF handle all the state of your form
use RHF's useFieldArray for managing (add, remove) your packages/subscriptions - there is no need to use watch here
use a separate useForm for your <AddPackage /> component, this has the benefit that you will have form validation for this sub form (in case it should be a requirement that all fields of <AddPackage /> need to be required) - i added validation in the demo to demonstrate this
AddPackage.tsx
export const AddSubscription: React.FC<AddSubscriptionProps> = ({ onAdd }) => {
const {
control,
reset,
handleSubmit,
formState: { errors }
} = useForm<Subscription>({
defaultValues: { from: null, to: null, package: null }
});
const clear = () => reset();
const add = handleSubmit((subscription: Subscription) => {
onAdd(subscription);
clear();
});
return (
<Card variant="outlined">
<LocalizationProvider dateAdapter={AdapterDateFns}>
<Grid container spacing={1} p={2}>
<Grid item container spacing={1} xs={12}>
<Grid item xs={6}>
<Controller
name="from"
control={control}
rules={{ required: "Required" }}
render={({ field }) => (
<DatePicker
{...field}
label="From"
renderInput={(params) => (
<TextField
{...params}
fullWidth
error={!!errors.from}
helperText={errors.from?.message}
/>
)}
/>
)}
/>
</Grid>
<Grid item xs={6}>
<Controller
name="to"
control={control}
rules={{ required: "Required" }}
render={({ field }) => (
<DatePicker
{...field}
label="To"
renderInput={(params) => (
<TextField
{...params}
fullWidth
error={!!errors.to}
helperText={errors.to?.message}
/>
)}
/>
)}
/>
</Grid>
</Grid>
<Grid item xs={12}>
<Controller
name="package"
control={control}
rules={{ required: "Required" }}
render={({ field: { onChange, ...field } }) => (
<Autocomplete
{...field}
options={packages}
onChange={(e, v) => onChange(v)}
renderInput={(params) => (
<TextField
{...params}
label="Package"
fullWidth
error={!!errors.package}
helperText={errors.package && "Required"}
/>
)}
/>
)}
/>
</Grid>
<Grid item xs={12}>
<Stack spacing={1} direction="row" justifyContent="end">
<Button variant="outlined" onClick={clear}>
Clear
</Button>
<Button variant="contained" onClick={add} type="submit">
Add
</Button>
</Stack>
</Grid>
</Grid>
</LocalizationProvider>
</Card>
);
};
Form.tsx
export default function Form() {
const { control, handleSubmit } = useForm<FormValues>({
defaultValues: {
seats: "",
addOns: false
}
});
const { fields, append, remove } = useFieldArray({
control,
name: "subscriptions"
});
const onSubmit = (data) => console.log("data", data);
return (
<form onSubmit={handleSubmit(onSubmit)}>
<Grid container spacing={2}>
<Grid item xs={12}>
<Box display="flex" justifyContent="end" gap={1}>
<Button variant="outlined">Cancel</Button>
<Button variant="contained" type="submit">
Save
</Button>
</Box>
</Grid>
<Grid item xs={12}>
<Controller
name="seats"
control={control}
render={({ field }) => (
<TextField {...field} fullWidth label="Seats" />
)}
/>
</Grid>
<Grid item xs={12}>
<AddSubscription onAdd={append} />
</Grid>
<Grid item xs={12}>
<List>
{fields.map((field, index) => (
<ListItem
key={field.id}
secondaryAction={
<IconButton
edge="end"
aria-label="delete"
onClick={() => remove(index)}
>
<DeleteIcon />
</IconButton>
}
>
<ListItemText
primary={field.package.label}
secondary={
<span>
{formatDate(field.from)} - {formatDate(field.to)}
</span>
}
/>
</ListItem>
))}
</List>
</Grid>
<Grid item xs={12}>
<Controller
name="addOns"
control={control}
render={({ field: { value, onChange } }) => (
<FormControlLabel
control={<Checkbox checked={!!value} onChange={onChange} />}
label="Add-ons"
/>
)}
/>
</Grid>
</Grid>
</form>
);
}

React JS Typescript input onChange and onFocus error

I want to implement the following repo available on Github using ReactJS Typescript. I created 3 different methods as onChange, changeHandler, focusHandler but they are not working correctly. When I click on the Card Number field, I get a 'number.replace' error.
I need to fix onChange and onFocus methods in TextField fields.
https://github.com/amaroteam/react-credit-cards
import React, {useState, FocusEvent, ChangeEvent} from 'react'
import Cards from 'react-credit-cards';
import 'react-credit-cards/es/styles-compiled.css'
const PaymentMethodEditor = () => {
const [stateList, setState] = React.useState(initialValues)
const handleFormSubmit = async (values: any) => {
console.log(values)
}
const focusHandler = (event: React.FocusEvent<HTMLInputElement>) => {
setState({ focus: event.target.name })
}
const changeHandler = (event: React.ChangeEvent<HTMLInputElement>) => {
const { name, value } = event.target;
setState({ [name]: event.target.value })
}
onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const newValue = e.currentTarget.value;
setState({ [name]: event.target.value })
}
return (
<CustomerDashboardLayout>
<DashboardPageHeader
icon={CreditCard}
title={`${id === 'add' ? 'Add New' : 'Edit'} Payment Method`}
button={
<Link href="/payment-methods">
<Button color="primary" sx={{ bgcolor: 'primary.light', px: '2rem' }}>
Back to Payment Methods
</Button>
</Link>
}
/>
<div id="PaymentForm">
<Cards
cvc={stateList.cvc}
expiry={stateList.exp}
focused={stateList.focus}
name={stateList.name}
number={stateList.card_no}
/>
<Card1>
<Formik
initialValues={initialValues}
validationSchema={checkoutSchema}
onSubmit={handleFormSubmit}
>
{({ values, errors, touched, handleChange, handleBlur, handleSubmit }) => (
<form onSubmit={handleSubmit}>
<Box mb={4}>
<Grid container spacing={3}>
<Grid item md={6} xs={12}>
<TextField
name="card_name"
label="Card Name"
fullWidth
onBlur={handleBlur}
onChange={changeHandler}
onFocus={focusHandler}
value={values.card_name || ''}
error={!!touched.card_name && !!errors.card_name}
helperText={touched.card_name && errors.card_name}
/>
</Grid>
<Grid item md={6} xs={12}>
<TextField
name="card_no"
label="Card Number"
fullWidth
onBlur={handleBlur}
onChange={changeHandler}
onFocus={focusHandler}
value={values.card_no || ''}
error={!!touched.card_no && !!errors.card_no}
helperText={touched.card_no && errors.card_no}
/>
</Grid>
<Grid item md={6} xs={12}>
<TextField
name="name"
label="Name on Card"
fullWidth
onBlur={handleBlur}
onChange={handleChange}
value={values.name || ''}
error={!!touched.name && !!errors.name}
helperText={touched.name && errors.name}
/>
</Grid>
<Grid item md={6} xs={12}>
<TextField
name="exp"
label="Exp. Date"
fullWidth
onBlur={handleBlur}
onChange={handleChange}
value={values.exp || ''}
error={!!touched.exp && !!errors.exp}
helperText={touched.exp && errors.exp}
/>
</Grid>
<Grid item md={6} xs={12}>
<TextField
name="cvc"
label="CVC"
fullWidth
onBlur={handleBlur}
onChange={handleChange}
value={values.cvc || ''}
error={!!touched.cvc && !!errors.cvc}
helperText={touched.cvc && errors.cvc}
/>
</Grid>
</Grid>
</Box>
<Button type="submit" variant="contained" color="primary">
Save Changes
</Button>
</form>
)}
</Formik>
</Card1>
</div>
</CustomerDashboardLayout>
)
}
const initialValues = {
card_no: '',
name: '',
exp: '',
cvc: '',
focus: '',
number: '',
card_name: '',
}
export default PaymentMethodEditor
enter image description here
enter image description here

React formik Validation Error Api Renders Every Time when other field validate

I've created a register form I tried to validate the form onBlur and the one has an email check with backend Apis, I have an issue when I validate any other that case mail check API render every time
I tried with onBlur and onChange validation false that case working fine, But I need onBlur validation, Any Ideas
Thanks for Help
const CompanyRegister = (props) => {
const classes = useStyles();
var [mailError, setMailError] = useState(false);
const initialValues = {
name: "",
website: "",
addressLine1: "",
city: "",
state: "",
mail: "",
};
const validationSchema = yup.object({
name: yup.string().strict().trim().required("Enter the ComapnyName"),
website: yup
.string()
.matches(
/((https?):\/\/)?(www.)?[a-z0-9]+(\.[a-z]{2,}){1,3}(#?\/?[a-zA-Z0-9#]+)*\/?(\?[a-zA-Z0-9-_]+=[a-zA-Z0-9-%]+&?)?$/,
"Enter correct url!"
)
.strict()
.trim()
.required("Enter the Website"),
pincode: yup.number("Invalid pincode").positive("Invalid pincode"),
phone: yup.number("InValid Phone Number"),
altPhone: yup.number("InValid Phone Number"),
mail: yup
.string()
.email("Enter correct Format")
.strict()
.trim()
.required("Enter the Correct Email"),
});
const validCheck = (data) => {
var mailData = { mail: data };
axios.post(baseurl + "companymailcheck", mailData).then((res) => {
if (res.data == "Invalid") {
setMailError(true);
} else {
setMailError(false);
}
});
};
const onSubmit = (data) => {
axios
.post(baseurl + "companyregisteration", data)
.then((res) => {
history.push(`/login`);
toast.success("Successfully Created");
})
.catch((err) => {
toast.error("Some Thing Error");
});
};
return (
<>
<div className={classes.back}>
<Link to="/">Home</Link>
</div>
<Container component="main" className={classes.layout}>
<div className={classes.paper}>
<Typography component="h1" variant="h5">
Register
</Typography>
<Formik
initialValues={initialValues}
onSubmit={onSubmit}
validateOnChange={false}
validateOnBlur={true}
validationSchema={validationSchema}
>
{({ values, isValid }) => {
return (
<Form autoComplete="off">
<Grid container spacing={4}>
<Grid item xs={12} sm={6}>
<Field
as={TextField}
name="name"
fullWidth
label="Company Name"
autoFocus
required
/>
<ErrorMessage name="name">
{(error) => (
<div className={classes.error}>{error}</div>
)}
</ErrorMessage>
</Grid>
<Grid item xs={12} sm={6}>
<Field
as={TextField}
name="website"
fullWidth
label="Website"
required
/>
<ErrorMessage name="website">
{(error) => (
<div className={classes.error}>{error}</div>
)}
</ErrorMessage>
</Grid>
<Grid item xs={12} sm={12}>
<Field
as={TextField}
name="addressLine1"
type="text"
fullWidth
label="Address Line1"
/>
</Grid>
<Grid item xs={12} sm={6}>
<Field
as={TextField}
name="mail"
fullWidth
label="Mail"
required
validate={() => validCheck(values.mail)}
/>
<ErrorMessage name="mail">
{(error) => (
<div className={classes.error}>{error}</div>
)}
</ErrorMessage>
{mailError ? (
<span style={{ color: "red" }} id="errormessage">
Mail Already There!
</span>
) : null}
</Grid>
<Button
type="submit"
fullWidth
variant="contained"
color="primary"
className={classes.submit}
disabled={!isValid || mailError}
>
Register
</Button>
</Grid>
</Form>
);
}}
</Formik>
</div>
</Container>
</>
);
};
export default CompanyRegister;
As long as it's fine to perform the validation during form submission then I would extend the onSubmit and put the check there.
You can use the second parameter which will return the FormikBag containing all relevant setter's to invalidate the form-field properly. Reference: https://formik.org/docs/api/formik#onsubmit-values-values-formikbag-formikbag--void--promiseany
In this case I would use setFieldError(field, message). Reference: https://formik.org/docs/api/formik#setfielderror-field-string-errormsg-string--void
<Formik initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={(values, {setFieldError}) => {
return validateMail(values.mail)
.then(() => {
// all good - continue with your submit handler
return onSubmit(values)
})
.catch(error => {
// something wrong? validate the error response + validation message OR set it statically.
setFieldError('mail', 'Mail Already There!')
})
}}
>

React useEffect(), fetch data with React Hooks and set the formik form

I want to fetch these (title, description, category) values to the following form. how can I do this?. I'm working on a Formik form that needs to adjust dynamically depending on data. I want to set data to the correct form field when the user going to edit something. I think something missing in my code. any help would be great.
const PostEdit = ({ match, history }) => {
const postId = match.params.id
//Data
const [initialValues, setInitialValues] = useState({
title: '',
description: '',
category: '',
})
const dispatch = useDispatch()
const postDetails = useSelector((state) => state.postDetails)
const { loading, error, post} = postDetails
useEffect(() => {
if (!post.title || post._id !== postId) {
dispatch(listPostDetails(postId))
} else {
setInitialValues({
title: post.title,
description: post.description,
category: post.category
})
}
}, [dispatch, history, postId, post,])
const submitHandler = () => {}
return (
<>
<div>
<Grid>
<Grid item xs={12}>
<Papervariant='outlined'>
<Formik
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={submitHandler}
>
{({ dirty, isValid, values }) => {
return (
<Form>
<DialogContent>
<Grid item container spacing={1} justify='center'>
<Grid item xs={12} sm={12} md={12}>
<Field
label='Title'
name='title'
required
value={values.title}
component={TextField}
/>
</Grid>
<Grid item xs={12} sm={12} md={12}>
<Field
label='Description'
name='description'
value={values.description}
component={TextField}
/>
</Grid>
<Grid item xs={12} sm={12} md={12}>
<Field
label='Category'
name='category'
value={values.category}
component={TextField}
/>
</Grid>
</Grid>
</DialogContent>
<DialogActions>
<Button
disabled={!dirty || !isValid}
variant='contained'
type='Submit'
>
Add
</Button>
</DialogActions>
</Form>
)
}}
</Formik>
</Paper>
</Grid>
</Grid>
</div>
</>
)
}
export default PostEdit
You are missing this prop
enaleReinitialize={true}
So, it should be something like this
<Formik
enableReinitialize={true} // You missed this prop
validateOnChange={true}
initialValues={initialValues}
Formik can be use as hook. https://formik.org/docs/api/useFormik
It'll exposed a function setValues and you can use it to dynamically change the form data

Can't add items to material-ui form

I got handed down a project from someone else and I need to add some items to a form created with react and material-ui. I can get text fields to work but if I try to add a dropdown, it doesn't hold the value when selected.
I followed the same conventions of adding the items to the form that the guy who created this form used.
I added a grid item with a formcontrol component inside of it. There was also defaultprops set with a "game" object inside, that had all of the form fields as properties. I added the new field items to there also.
Here is the whole form component because I'm not really sure where the problem actually is.
import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import history from '~/utils/history';
import { FormControl, Button, TextField, Grid, MenuItem, FormHelperText } from '#material-ui/core';
import { DateTimePicker } from 'material-ui-pickers';
import gameState from '~/utils/enums';
import { dateTime } from '~/utils/formats';
import { getById, create, update, remove } from '~/services/games';
import { getAll as getLeagues } from '~/services/leagues';
import { getAll as getSeasons } from '~/services/seasons';
import { getAll as getTeams } from '~/services/teams';
const GameForm = ({ game, id }) => {
useEffect(() => {
console.log({ form, game });
});
const [edit, setEdit] = useState(false);
const [form, setForm] = useState(game);
const [error, setError] = useState('');
const [variant, setVariant] = useState('outlined');
const [leagues, setLeagues] = useState([]);
const [seasons, setSeasons] = useState([]);
const [teams, setTeams] = useState([]);
const [gametype, setGametype] = useState(1);
const gametypes = [
{ key: 0, value: 'Series Game' },
{ key: 1, value: 'Playoff' },
{ key: 2, value: 'Final' },
{ key: 3, value: 'Else' }
];
useEffect(() => {
getSeasons()
.then(({ data }) => {
setSeasons(data);
return getLeagues();
})
.then(({ data }) => {
setLeagues(data);
if (id) {
getById(id).then(({ data }) => setForm(data));
} else {
setEdit(true);
}
});
}, []);
useEffect(() => {
if (edit) {
setVariant('outlined');
} else {
setVariant('standard');
}
}, [edit]);
useEffect(() => {
if (form.league) {
getTeams({ leagues: [form.league] }).then(({ data }) => setTeams(data));
}
}, [form.league]);
useEffect(() => {
if (form.gametype) {
setGametype('Playoff');
}
}, [form.gametype]);
const handleChange = ({ target }) => {
let { name, value } = target;
setForm({
...form,
[name]: value
});
};
const handleDateChange = formInputName => {
const dateHandler = moment => {
setForm({
...form,
[formInputName]: moment ? moment.toDate() : null
});
};
return dateHandler;
};
const handleFormSubmit = () => {
if (!edit) {
setEdit(true);
} else {
new Promise(resolve => {
resolve(form._id ? update(form) : create(form));
})
.then(() => {
history.push('/games');
})
.catch(error => setError(error.response.data.error));
}
};
const handleDelete = () => {
if (window.confirm(`Delete permanently?`)) {
remove(id).then(() => history.goBack());
}
};
const handleCancel = () => {
if (edit && id) {
setEdit(false);
} else {
history.goBack();
}
};
return (
<Grid container spacing={8} justify="space-between">
<Grid item xs={12} md={6}>
<FormControl margin="normal" required fullWidth variant="outlined">
<TextField
required
select
id="season"
name="season"
label="Season"
variant={variant}
disabled={!edit}
value={form.season}
onChange={handleChange}
>
{seasons.map(option => (
<MenuItem key={option.name} value={option._id}>
{option.name}
</MenuItem>
))}
</TextField>
</FormControl>
</Grid>
<Grid item xs={12} md={6}>
<FormControl margin="normal" required fullWidth variant="outlined">
<TextField
required
select
id="league"
name="league"
label="League"
variant={variant}
disabled={!edit}
value={form.league}
onChange={handleChange}
>
{leagues.map(option => (
<MenuItem key={option.name} value={option._id}>
{option.name}
</MenuItem>
))}
</TextField>
</FormControl>
</Grid>
<Grid item xs={12}>
<FormControl margin="normal" required fullWidth variant="outlined">
<DateTimePicker
required
id="start"
name="start"
label="Game starts"
variant={variant}
disabled={!edit || !form.season}
autoOk
ampm={false}
keyboard
clearable
minDate={form.season ? seasons.find(({ _id }) => _id === form.season).start : undefined}
minDateMessage="Cannot start before the season begins"
maxDate={form.season ? seasons.find(({ _id }) => _id === form.season).end : undefined}
maxDateMessage="Cannot start after the end of the season"
value={form.start}
onChange={handleDateChange('start')}
{...dateTime}
/>
<FormHelperText disabled={!form.season}>
{!form.season ? 'Select season first' : undefined}
</FormHelperText>
</FormControl>
</Grid>
<Grid item xs={12} md={6}>
<FormControl margin="normal" required fullWidth variant="outlined">
<TextField
required
select
id="home"
name="home"
label="Home team"
variant={variant}
disabled={!edit || !form.league}
helperText={!form.league ? 'Select league first' : undefined}
value={form.home}
onChange={handleChange}
>
<MenuItem value="">
<em>None</em>
</MenuItem>
{teams
.filter(({ _id }) => _id !== form.away)
.map(option => (
<MenuItem key={option.name} value={option._id}>
{option.name}
</MenuItem>
))}
</TextField>
</FormControl>
</Grid>
<Grid item xs={12} md={6}>
<FormControl margin="normal" required fullWidth variant="outlined">
<TextField
required
select
id="away"
name="away"
label="Team away"
variant={variant}
disabled={!edit || !form.league}
helperText={!form.league ? 'Select league first' : undefined}
value={form.away}
onChange={handleChange}
>
<MenuItem value="">
<em>None</em>
</MenuItem>
{teams
.filter(({ _id }) => _id !== form.home)
.map(option => (
<MenuItem key={option.name} value={option._id}>
{option.name}
</MenuItem>
))}
</TextField>
</FormControl>
</Grid>
<Grid item xs={12} md={6}>
<FormControl margin="normal" required fullWidth variant="outlined">
<TextField
required
select
id="gametype"
label=" Game type"
variant={variant}
disabled={!edit}
value={form.gametype}
onChange={handleChange}
>
<MenuItem value="">
<em>None</em>
</MenuItem>
{gametypes.map(option => (
<MenuItem key={option.key} value={option.value}>
{option.value}
</MenuItem>
))}
</TextField>
</FormControl>
</Grid>
<Grid item xs={12} md={6}>
<FormControl margin="normal" required fullWidth variant="outlined">
<TextField
text
id="umpire"
label="Umpire"
variant={variant}
disabled={!edit || !form.league}
/>
</FormControl>
</Grid>
<Grid item xs={12} md={6}>
<FormControl margin="normal" required fullWidth variant="outlined">
<TextField
text
id="scorekeeper"
label="Scorekeeper"
variant={variant}
disabled={!edit || !form.league}
/>
</FormControl>
</Grid>
<Grid item xs={12} md={6}>
<FormControl margin="normal" required fullWidth variant="outlined">
<TextField
text
id="referee1"
label="Referee 1"
variant={variant}
disabled={!edit || !form.league}
/>
</FormControl>
</Grid>
<Grid item xs={12} md={6}>
<FormControl margin="normal" required fullWidth variant="outlined">
<TextField
text
id="referee2"
label="Referee 2"
variant={variant}
disabled={!edit || !form.league}
/>
</FormControl>
</Grid>
<Grid item xs={12} md={6}>
<FormControl margin="normal" required fullWidth variant="outlined">
<TextField
text
id="referee3"
label="Referee 3"
variant={variant}
disabled={!edit || !form.league}
/>
</FormControl>
</Grid>
<Grid item xs={edit && id ? 4 : 6}>
<Button variant="outlined" color="secondary" fullWidth onClick={handleCancel}>
{edit && id ? 'Cancel' : 'Back'}
</Button>
</Grid>
{edit && id ? (
<Grid item xs={4}>
<Button
type="submit"
variant="contained"
color="secondary"
fullWidth
onClick={handleDelete}
>
Delete
</Button>
</Grid>
) : null}
<Grid item xs={edit && id ? 4 : 6}>
<Button
type="submit"
variant="outlined"
color="primary"
fullWidth
onClick={handleFormSubmit}
>
{edit ? (id ? 'Save' : 'Create') : 'Edit Game'}
</Button>
</Grid>
{!edit ? (
<Grid item xs={12}>
<Button
variant="outlined"
color="primary"
fullWidth
onClick={() => {
history.push('/games/' + id + '/scores');
}}
>
EDIT SCORES
</Button>
</Grid>
) : null}
</Grid>
);
};
GameForm.defaultProps = {
game: {
season: '',
league: '',
start: null,
home: '',
away: '',
gametype: '',
umpire: '',
scorekeeper: '',
referee1: '',
referee2: '',
referee3: ''
}
};
GameForm.propTypes = {
//classes: PropTypes.object.isRequired,
game: PropTypes.object
};
export default GameForm;
I noticed that if I print the game object to the console, it only shows the old form items and not the new ones I added. The new items are: gametype, umpire, scorekeeper, referee1-3.
I've been trying to make this work for a few days already, so any help would really be appreciated.
you need onChange={handleChange} in those and you also need to provide the name as props
BTW, I highly recommend you to combine those useStates as one single state object
For example, an alternative banned multiple useState() calls in a component. You’d keep state in one object.
function Form() {
const [state, setState] = useState({
edit: '',
form: '',
error: '',
});
// ...
}
To be clear, Hooks do allow this style. You don’t have to split your state into a bunch of state variables (see doc).

Resources