'React Form Submission for Firebase Firestore
i am trying to pass form data for a recipe project i am doing to a firestore back end. So far i have:
- Successfully added the Firestore back end and tested it works
- Created a button on the Firestore Component and passed data to it via props
- Created a submit handler and can console log my data, that i ultimately wnat to pass and save in firestore
Problems i think i have:
- My AddRecipe component is getting large (maybe thats the nature of what i am doing but am aware you want to break down into resuable components where possible) It could be i have got my child / parents
- I have maybe got my child / parent model in a muddle
- General housekeeping (import effeciency etc)
- List item
Firebase Config (with some hard coding i used for testing)
import firebase from 'firebase/compat/app'
import 'firebase/compat/firestore'
import Button from '@mui/material/Button'
import AddRecipe from '../../../pages/recipes/addrecipe'
const WriteRecipe = () => {
const sendData = () => {
console.log(props)
try {
firebase
.firestore()
.collection('recipes')
.doc(props.recipeId)
.set({
arrayData: ['Macaroni Cheese', 2, 'it is delicious',]
})
.then(alert('Data Was successfully sent to Back end'))
}
catch (error) {
console.log(error)
alert(error)
}
}
return (
{/* used to return a button, now null*/ })
}
export default WriteRecipe
import { useState } from 'react'
import Typography from '@mui/material/Typography'
import Grid from '@mui/material/Grid'
import TextField from '@mui/material/TextField'
import makeStyles from '@mui/styles/makeStyles'
import MenuItem from '@mui/material/MenuItem';
import Button from '@mui/material/Button'
import IconButton from '@mui/material/Icon'
import { v4 as uuidv4 } from 'uuid';
import Divider from '@mui/material/Divider';
import AddIcon from '@mui/icons-material/Add';
import RemoveIcon from '@mui/icons-material/Remove';
import WriteRecipe from '../../src/components/firebase/WriteRecipe'
import ReadRecipe from '../../src/components/firebase/ReadRecipe'
import initFirebase from '../../firebase/initFirebase'
initFirebase()
const useStyles = makeStyles({
field: {
marginTop: 10,
marginBottom: 40,
display: 'block'
},
submit: {
martinTop: 10,
marginLeft: 20
},
})
const category = [
{
value: 'Starter',
label: 'Starter',
},
{
value: 'Main',
label: 'Main',
},
{
value: 'Dessert',
label: 'Dessert',
},
];
const serves = [
{
value: 1,
label: '1',
},
{
value: 2,
label: '2',
},
{
value: 3,
label: '3',
},
{
value: 4,
label: '4',
},
{
value: 5,
label: '5',
},
];
const AddRecipe = () => {
const classes = useStyles()
const [inputFields, setInputFields] = useState([
{ id: uuidv4(), firstName: '', lastName: '' },
]);
const handleIngredientChangeInput = (id, event) => {
const newInputFields = inputFields.map(i => {
if (id === i.id) {
i[event.target.name] = event.target.value
}
return i;
})
}
const [title, setTitle] = useState('')
const [Description, setDescription] = useState('')
const [Author, setAuthor] = useState('')
const [Category, setCategory] = useState('')
const [Url, setUrl] = useState('')
const [Serves, setServes] = useState('')
const [Directions, setDirections] = useState('')
const handleAddIngredients = () => {
event.preventDefault()
setInputFields([...inputFields, { id: uuidv4(), firstName: '', lastName: '' }])
}
const handleRemoveIngredients = id => {
event.preventDefault()
const values = [...inputFields];
values.splice(values.findIndex(value => value.id === id), 1);
setInputFields(values);
}
const handleSubmit = (event) => {
event.preventDefault()
if (title && Description && Author && Category && Directions)
console.log(title, Description, Author, Category.at, Url, Serves, Directions)
}
return (
<Grid container direction="column" >
<form noValidate autocomplete="off" onSubmit={handleSubmit}>
<Grid item xs={6} md={12} style={{ marginBottom: "0.5em" }}>
<TextField
onChange={(event) => setTitle(event.target.value)}
sx={{ m: 1, width: '50ch' }}
label="Title"
variant="outlined"
color="secondary"
size="medium"
required>
</TextField>
<TextField
onChange={(event) => setDescription(event.target.value)}
sx={{ m: 1, width: '50ch' }}
label="Description"
variant="outlined"
color="secondary"
size="medium"
required>
</TextField>
<TextField
onChange={(event) => setAuthor(event.target.value)}
sx={{ m: 1, width: '50ch' }}
label="Author"
variant="outlined"
color="secondary"
size="medium"
required></TextField>
</Grid>
<Grid item xs={6} md={6} style={{ marginBottom: "0.5em" }}>
<TextField
onChange={(event) => setCategory(event.target.value)}
sx={{ m: 1, width: '50ch' }}
label="Select Category"
variant="outlined"
color="secondary"
select
size="medium"
required>
{category.map((option) => (
<MenuItem key={option.value} value={option.value}>
{option.label}
</MenuItem>
))}
</TextField>
<TextField
onChange={(event) => setUrl(event.target.value)}
sx={{ m: 1, width: '50ch' }}
label="URL(Where applicable):"
variant="outlined"
color="secondary"
size="medium"
r>
</TextField>
</Grid>
<Grid item xs={6} md={6} style={{ marginBottom: "0.5em" }}>
<TextField
onChange={(event) => setServes(event.target.value)}
sx={{ m: 1, width: '50ch' }}
label="Serves"
variant="outlined"
color="secondary"
select
size="medium"
required>
{serves.map((option) => (
<MenuItem key={option.value} value={option.value}>
{option.label}
</MenuItem>
))}
</TextField>
</Grid>
<Grid item xs={6} md={6} style={{ marginBottom: "3.0em" }}>
<Divider sx={{ borderBottomWidth: 5, bgcolor: "primary", width: '210ch' }} classes={{ root: classes.dividerColor }}></Divider>
</Grid>
<Grid item xs={12} style={{ marginBottom: "1.5em" }}>
{inputFields.map(inputField => (
<div key={inputField.id}>
<TextField sx={{ marginBottom: '1em', marginRight: '1em' }}
key={inputField.id}
name="ingredients"
label="Ingredients"
variant="outlined"
color="secondary"
/*value={inputField.firstName} -- Important for later perhaps*/
onChange={event => handleIngredientChangeInput(inputField.id, event)}
/>
<TextField sx={{ marginBottom: '1em', marginRight: '1em' }}
key={inputField.id}
name="quantity"
label="Quantity"
variant="outlined"
color="secondary"
/*value={inputField.firstName} -- Important for later perhaps*/
onChange={event => handleIngredientChangeInput(inputField.id, event)}
/>
<IconButton size="large" sx={{ marginTop: '0.5em', marginRight: '1em' }}
type="submit"
colour="secondary"
onClick={handleAddIngredients}>
<AddIcon />
</IconButton>
<IconButton sx={{ marginTop: '0.5em' }}
type="submit"
colour="secondary"
variant="contained" onClick={handleRemoveIngredients}>
<RemoveIcon />
</IconButton>
</div>
))}
</Grid>
<Grid item>
<TextField
onChange={(event) => setDirections(event.target.value)}
label="Directions"
variant="outlined"
color="secondary"
required
multiline
rows={10}
sx={{ width: '150ch' }}
/>
</Grid>
<Grid item>
<Button sx={{ mt: 5, marginBottom: '6em', marginLeft: '30em' }}
type="submit"
colour="secondary"
variant="contained">
Happy Cooking!</Button>
</Grid>
</form>
<ReadRecipe />
</Grid >
)
}
export default AddRecipe
Quite inexperienced (First Project i am doing after courses) so any help would be massively appreciated, banging my head off the wall!
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
