Formik TextFields are not updated once component is rendered - reactjs

I'm fetching data from the server once component mounts, when I console.log(data) browser shows proper data.
I want to use Formik and MIU TextFields to display data which later on will be updated
const [data, setData] = useState([
{
action: "",
description: "",
tag: "",
category: "",
},
]);
console.log(data);
const [initialValues, setInitialValues] = useState([
{
action: "",
description: "",
tag: "",
category: "",
},
]);
useEffect(() => {
getData();
}, []);
useEffect(() => {
setInitialValues(data);
}, [data]);
const { values, handleChange, handleSubmit, resetForm } = useFormik({
initialValues: initialValues,
validationSchema,
onSubmit: () => {
console.log(values);
axios({
method: "POST",
url: "http://localhost:5000/allActions",
values,
}).then((response) => {
console.log(response);
});
resetForm();
},
});
This is Data component which displays TextFields
const Data = () => {
return (
<form onSubmit={handleSubmit}>
{!data[0].action && "...Loading"}
{data &&
data.map((element, idx) => (
<div key={idx} style={{ marginBottom: "100px" }}>
<Box sx={{ margin: "40px", padding: "20px" }}>
<TextField
variant="outlined"
label="action"
id={`action-${idx}`}
name={`values[${idx}].action`}
value={values[idx]?.action}
onChange={handleChange}
/>
</Box>
<Box sx={{ margin: "40px", padding: "20px" }}>
<TextField
variant="outlined"
label="Description"
id={`desciption-${idx}`}
name={`values[${idx}].description`}
value={values[idx]?.description}
onChange={handleChange}
/>
</Box>
<Box sx={{ margin: "40px", padding: "20px" }}>
<TextField
variant="outlined"
label="tag"
id={`id-${idx}`}
name={`values[${idx}].tag`}
value={values[idx]?.tag}
onChange={handleChange}
/>
</Box>
<Box sx={{ margin: "40px", padding: "20px" }}>
<TextField
variant="outlined"
label="category"
id={`category-${idx}`}
name={`values[${idx}].category`}
value={values[idx]?.category}
onChange={handleChange}
/>
</Box>
</div>
))}
<Button color="primary" variant="contained" type="submit">
Update
</Button>
</form>
);
};
The outcome of above code is that is displays proper amount of TextFields, in this case 3 blocks of 4 TextFields, but it's all empty, none of TextField have filled data which is displayed in console.
Can You please suggest what is wrong that TextFields are not updated ?

Related

How can we validate our form using formik

I am unable to validate the following form because of checkbox handling. I have to implement this type of thing in many of my form issue is same i am unable to handle the on change on some of that form to handle the checkbox.
import React, { useEffect } from "react";
import {
Grid,
Typography,
Button,
Box,
TextField,
FormControlLabel,
} from "#mui/material";
import { Formik, Form, Field, ErrorMessage } from "formik";
import axios from "axios";
import * as Yup from "yup";
import API from "../../../../../E2E/Axios.Utils";
const AddReport = ({
handleDialog,
update,
setUpdate,
setAlert,
setAlertContent,
setAlertType,
}) => {
const [tabData, setTabData] = React.useState([]);
const token = localStorage.getItem("token").toString();
const onSubmit = (values, props) => {
console.log("values", values);
const tabs = [];
values.tab_id.map((ele) => {
if (typeof ele === "string") {
tabs.push(Number(ele));
}
console.log("tabs", tabs);
return tabs;
});
const data = {
report_type_name: values.report_type_name,
description: values.description,
tab_id: tabs,
remember: false,
};
API.post("/app/secure/report_type/", data, {
headers: { Authorization: `Bearer ${token}` },
})
.then((res) => {
handleDialog();
setUpdate(update + 1);
setAlertContent(res.data.msg);
setAlertType("success");
setAlert(true);
})
.catch((err) => {
console.log(err);
if (err?.response?.status == 401) {
setAlertContent("Token is invalid or expired.");
setAlertType("error");
setAlert(true);
} else {
setAlertContent(`Error : Something went wrong.`);
setAlertType("error");
setAlert(true);
}
});
props.resetForm();
};
This API is used to get the tab details
const getTabData = () => {
API.get("/app/secure/my_tab/", {
headers: { Authorization: `Bearer ${token}` },
})
.then((res) => {
console.log("GetData", res);
setTabData(res.data.tab_list);
console.log(res.data);
})
.catch((err) => {
console.log(err);
});
};
useEffect(() => {
getTabData();
}, []);
const initialValues = {
report_type_name: "",
description: "",
tab_id: [],
remember: false,
};
const AlphaNumeric = /^[a-zA-Z0-9](([_ -])?[a-zA-Z0-9]*)+$/;
const validationSchema = Yup.object().shape({
report_type_name: Yup.string()
.matches(AlphaNumeric, "Please enter valid report type name.")
.max(40, "Tab Name must be at most 40 characters.")
.required("This field is required."),
description: Yup.string()
.matches(AlphaNumeric, "Please enter valid description.")
.max(160, "Description must be at most 160 characters.")
.required("This field is required."),
});
return (
<Box>
<Typography
id="modal-modal-title"
variant="h6"
component="h2"
sx={{ marginBottom: "4%" }}
>
Add Report
</Typography>
<Box>
<Formik
initialValues={initialValues}
onSubmit={onSubmit}
validationSchema={validationSchema}
>
{(props) => (
<Form noValidate>
<Field
as={TextField}
name="report_type_name"
label="Name"
placeholder="Name"
fullWidth
error={
props.errors.report_type_name &&
props.touched.report_type_name
}
size="small"
helperText={<ErrorMessage name="report_type_name" />}
required
sx={{ marginBottom: "4%" }}
/>
<Field
as={TextField}
name="description"
label="Description"
placeholder="Description"
fullWidth
error={props.errors.description && props.touched.description}
size="small"
helperText={<ErrorMessage name="description" />}
required
sx={{ marginBottom: "4%" }}
/>
<Typography variant="subtitle1" sx={{ textAlign: "left" }}>
<span style={{ fontWeight: "bold" }}>Tabs</span>
</Typography>
<Grid container>
{tabData.map((item) => {
return (
<Grid
item
xl={4}
lg={4}
md={4}
sm={12}
xs={12}
key={item.tab_id}
style={{
display: "flex",
width: "150px",
}}
>
<FormControlLabel
control={
<Field
name="tab_id"
label={item.tab_name}
value={item.tab_id.toString()}
style={{ margin: "8px" }}
type="checkbox"
/>
}
/>
<div style={{ margin: "8px" }}>{item.tab_name}</div>
</Grid>
);
})}
</Grid>
<Grid
container
sx={{
display: "flex",
alignItems: "center",
justifyContent: "flex-end",
gap: "1rem",
mt: 2,
}}
>
<Grid item>
<Button onClick={handleDialog}>Disagree</Button>
</Grid>
<Grid item>
<Button
type="submit"
variant="contained"
sx={{
padding: "10px",
borderRadius: "20px",
width: "101px",
height: "36px",
}}
>
Save
</Button>
</Grid>
</Grid>
</Form>
)}
</Formik>
</Box>
</Box>
);
};
export default AddReport;
I have put all the code in this. facing same issue.
I dont know from where the error is coming.

Disable button on Form Submit in React

For some reason, my Sign In button does not become disabled when the form is submitted. Is there something obviously incorrect?
It is supposed to be disabled when processing a user's sign in API request.
This is also not a result of a fast API, because even if I set the network speed to very slow, it does not become disabled at any point.
import React, { useRef, useState } from 'react';
import { Link, useNavigate } from 'react-router-dom';
import {
Alert, Box, Card, TextField, Typography,
} from '#mui/material';
import LoadingButton from '#mui/lab/LoadingButton';
import { useAuth } from '../context/AuthContext';
import '../../pages/bg.css';
export default function SignInAuth() {
const emailRef = useRef();
const passwordRef = useRef();
const [error, setError] = useState('');
const [loading, setLoading] = useState(false);
const navigate = useNavigate();
const auth = useAuth();
async function handleSubmit(e) {
e.preventDefault();
if (!emailRef.current.value) {
return setError('Please enter an Email Address');
}
if (!passwordRef.current.value) {
return setError('Please enter a password');
}
setLoading(true);
setError('');
fetch(
`${process.env.REACT_APP_API_URL}auth/login`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({
Email: emailRef.current.value,
Password: passwordRef.current.value,
}),
},
).then((response) => {
if (response.ok) {
auth.signin(emailRef.current.value);
return navigate('/Dashboard');
}
// Response must be handled in a promise.
return response.json().then((errorText) => { throw new Error(errorText.message); });
}).then(setLoading(false)).catch((err) => {
setError(err.message); // This comes from the returned error promise.
// System throws error, and then error is set for the text.
});
return null;
}
const onSubmit = (e) => {
handleSubmit(e);
};
const textFieldStyle = {
width: '300px',
};
return (
<Box sx={{
zIndex: 1,
minWidth: '200px',
width: '450px',
}}
>
<Card sx={{ p: '20px', borderRadius: '15px' }}>
<Typography variant="h4" sx={{ fontWeight: 600, textAlign: 'center', mb: '8px' }}>Sign In</Typography>
<form onSubmit={(e) => onSubmit(e)}>
<Box sx={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
{error && <Alert severity="error" sx={{ ...textFieldStyle, my: '10px' }}>{error}</Alert>}
<TextField autoFocus margin="normal" inputRef={emailRef} type="email" id="email" label="Email" sx={textFieldStyle} />
<TextField margin="normal" inputRef={passwordRef} type="password" id="password" label="Password" sx={textFieldStyle} />
<LoadingButton
sx={{ mt: '16px', mb: '4px', width: '150px' }}
loading={loading}
variant="contained"
type="submit"
>
Sign In
</LoadingButton>
</Box>
</form>
<Typography variant="subtitle1" align="center" sx={{ mt: '10px' }}>
<Link to="/forgot-password">Forgot Password?</Link>
</Typography>
</Card>
<Box>
<Typography variant="subtitle1" align="center" sx={{ mt: '10px' }}>
Need an account?
{' '}
<Link to="/SignUp">Sign Up</Link>
</Typography>
</Box>
</Box>
);
}
According to the documentation, you must pass in a disabled prop to the LoadingButton component. Set it to be the same as your loading state.
<LoadingButton
sx={{ mt: '16px', mb: '4px', width: '150px' }}
loading={loading}
disabled={loading}
variant="contained"
type="submit"
>
Sign In
</LoadingButton>

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!

How to disable formik form after submission of form?

I have created a formik form that stores values at the backend. I have set-reset button, initial values. Everything working fine. But I can't able to find a way to disable formik form after submission of the form i.e if the user fills the form after a click on submit button user is not able to click on the text field.
// #ts-ignore
import React, { useState, useEffect } from 'react';
import { Formik, Form, Field } from 'formik';
import { Typography, Button, Grid } from '#material-ui/core';
import * as Yup from 'yup';
import { MyInput } from './comman/MyInput';
import { Textarea } from './comman/Textarea';
import { Event } from '../Tracking/Event';
const contactSchema = Yup.object().shape({
name: Yup.string().required('Please Enter Your Name'),
email: Yup.string()
.email('Please enter a valid email address')
.required('Please enter an email address'),
number: Yup.string()
.min(10, 'Must be 10 digit.')
.max(10, 'Must be 10 digit.'),
});
export default function ContactUs(props: any) {
const [submitted,setSubmittde] = useState(false);
const [state, setState] = useState({
msg: '',
});
const [selectedemail, setEmail] = useState({
text: '',
});
const [comname, setComname] = useState({
cName: '',
});
useEffect(() => {
fetch(`${window.location.href}`);
//const findemail = window.location.href;
const findemail =
'public/home';
const email =
findemail.match(/([a-zA-Z0-9._-]+#[a-zA-Z0-9._-]+\.[a-zA-Z0-9_-]+)/) ||
[];
const finalemail = email[0].toString();
const company = findemail.match(/(?<=%)\w+(?=&)/g) || [];
const finalcompany = company.toString();
setComname({ cName: finalcompany });
setEmail({ text: finalemail });
}, []);
return (
<div>
<img
src="public/logo"
width="200"
className="d-inline-block"
alt="logo"
style={{
marginTop: '2em',
marginBottom: '2em',
float: 'right',
}}
/>
<Formik
enableReinitialize
initialValues={{
name: '',
email: selectedemail.text,
number: '',
companyname: comname.cName,
message: '',
}}
validationSchema={contactSchema}
onSubmit={(values, { resetForm }) => {
const data = {
name: values.name,
email: values.email,
number: values.number,
companyname: values.companyname,
message: values.message,
formtype: 'Email Marketing Contactus',
};
const request = new Request(
`${process.env.REACT_APP_PRODUCTION_EMAILCONTACTUS_API}`,
{
method: 'POST',
headers: new Headers({
'Content-Type': 'application/json',
}),
body: JSON.stringify(data),
},
);
fetch(request)
.then((res) => res.json())
.then((data) => {
if (
data.message ===
'We have received your message and will get in touch shortly. Thanks!'
) {
setState({
msg: data.message,
});
} else {
console.log('error');
}
});
resetForm();
}}
>
{({ errors, touched }) => (
<Grid container>
<Grid item xs={12}>
<Typography
variant="body1"
style={{
marginTop: '1em',
fontFamily: 'roboto',
fontSize: '1.3rem',
color: '#2F4858',
}}
>
To know more please submit your information, and one of our
expert advisors will get in touch within 24 hours!{' '}
</Typography>
<br />
<Form>
<Typography
variant="h6"
style={{
fontFamily: 'roboto',
color: '#2F4858',
marginTop: '0.5em',
}}
>
Full Name
</Typography>
<Field
id="outlined-multiline-flexible"
type="text"
name="name"
placeholder="Name"
component={MyInput}
/>
<br />
{errors.name && touched.name ? (
<div className="text-danger" style={{ color: 'red' }}>
{errors.name}
</div>
) : null}
<Typography
variant="h6"
style={{ fontFamily: 'roboto', marginTop: '1em' }}
>
Email
</Typography>
<Field
type="email"
name="email"
placeholder="Email"
values={props.text}
style={{ color: 'white' }}
component={MyInput}
/>{' '}
<br />
{errors.email && touched.email ? (
<div className="text-danger" style={{ color: 'red' }}>
{errors.email}
</div>
) : null}
<Typography
variant="h6"
style={{
fontFamily: 'roboto',
color: '#2F4858',
marginTop: '1em',
}}
>
Mobile Number (Optional)
</Typography>
<Field
name="number"
placeholder="Contact Number"
component={MyInput}
// label="Contact Number"
/>
<br />
{errors.number && touched.number ? (
<div className="text-danger" style={{ color: 'red' }}>
{errors.number}
</div>
) : null}
<Typography
variant="h6"
style={{
fontFamily: 'roboto',
color: '#2F4858',
marginTop: '1em',
}}
>
Company Name (Optional)
</Typography>
<Field
name="companyname"
placeholder="Company Name"
// label="Contact Number"
component={MyInput}
/>
<br />
<Typography
variant="h6"
style={{
fontFamily: 'roboto',
color: '#2F4858',
marginTop: '1em',
}}
>
How can we help? (Optional)
</Typography>
<Field
id="outlined-multiline-static"
name="message"
placeholder="Your question about our services"
label="How can we help?"
component={Textarea}
/>
<br />
<br />
<Button
type="submit"
variant="contained"
onClick={() =>
Event(
'Contact from',
'Client submitted ',
'domain',
)
}
style={{
background: '#F79924',
color: 'white',
fontFamily: 'roboto',
fontSize: '1rem',
}}
>
Submit{' '}
</Button>
<br />
{state.msg && (
<Typography
variant="h6"
style={{
color: '#4BB543',
fontFamily: 'roboto-medium',
marginTop: '1em',
}}
>
{' '}
{state.msg}{' '}
</Typography>
)}
</Form>
</Grid>
</Grid>
)}
</Formik>
</div>
);
}
[![Formik form][1]][1]
I don't know how to disable formik form. Please help?
[1]: https://i.stack.imgur.com/PQXBV.png
This can be simply done using the disabled attribute and your existing value isSubmitted.
Pass a prop disabled into your custom input:
<Field
type="email"
name="email"
placeholder="Email"
values={props.text}
style={{ color: 'white' }}
component={MyInput}
disabled={isSubmitted}
/>
And apply it in the custom input using the ...props spread:
const MyInput = ({
field,
label,
name,
id,
value,
...props
}) => (
<div>
<label htmlFor="id">{label} </label>
<input id={id} type="text" {...field} {...props} />
</div>
);
And make sure you set isSubmitted somewhere in the onSubmit function
fetch(request)
.then((res) => res.json())
.then((data) => {
if (
data.message ===
'We have received your message and will get in touch shortly. Thanks!'
) {
setState({
msg: data.message,
});
setIsSubmitted(true);
} else {
console.log('error');
}
});
Live demo of a simple form that disables inputs/button after submission.

Trying to make a POST request to Firebase Firestore

import axios from 'axios'
import Copyright from '../components/Copyright'
// Material UI Stuff
import { makeStyles } from '#material-ui/core/styles'
import CircularProgress from '#material-ui/core/CircularProgress'
import Container from '#material-ui/core/Container'
import Typography from '#material-ui/core/Typography'
import TextField from '#material-ui/core/TextField'
import Button from '#material-ui/core/Button'
import Box from '#material-ui/core/Box'
const INITIAL_STATE = {
cohort: '',
program: '',
github: '',
website: '',
linkedIn: ''
}
const inputProps = {
step: 1,
min: 1,
max: 99
}
const Profile = () => {
const [formData, setFormData] = useState(INITIAL_STATE)
const [isloading, setIsLoading] = useState(false)
const [errors, setErrors] = useState({})
const [user, setUser] = useState(null)
const isInvalid = !formData.cohort || !formData.program || isloading
const handleInputChange = field => e => {
setFormData({ ...formData, [field]: e.target.value })
}
const fetchProfile = async () => {
const token = await localStorage.FBIdToken
await axios
.get(`/user`, {
headers: {
Authorization: `${token}`
}
})
.then(res => {
setUser(res.data)
setFormData({
...formData,
github: res.data.user.github ? res.data.user.github : '',
website: res.data.user.website ? res.data.user.website : '',
linkedIn: res.data.user.linkedIn ? res.data.user.linkedIn : '',
cohort: res.data.user.cohort,
program: res.data.user.program
})
})
.catch(err => console.log('*** WRONG ***'))
}
useEffect(() => {
fetchProfile()
}, [])
const handleSubmit = async e => {
e.preventDefault()
setIsLoading(true)
const fireToken = await localStorage.FBIdToken
await axios
.post(
(`/user`,
{
headers: {
Authorization: `${fireToken}`
}
})
)
.then(res => {
console.log(res.data)
setIsLoading(false)
})
.catch(err => {
console.log(err)
setIsLoading(false)
})
}
const useStyles = makeStyles(theme => ({
form: {
textAlign: 'center',
width: '100%', // Fix IE 11 issue.
marginTop: theme.spacing(1),
position: 'relative'
},
logo: {
width: 180,
height: 180,
display: 'block',
alignItems: 'center'
},
submit: {
margin: theme.spacing(3, 0, 2),
position: 'relative'
},
progress: {
position: 'absolute'
},
customError: {
color: 'red',
fontSize: '0.8rem',
width: '100%',
position: 'absolute'
}
}))
const classes = useStyles()
return (
<>
{user ? (
<div>
<Container component="main" maxWidth="xs">
<div className={classes.paper}>
<img
src={user.user.imageUrl}
alt="wyncode logo"
className={classes.logo}
/>
<Typography variant="h3" className={classes.pageTitle}>
Sign Up
</Typography>
<form noValidate onSubmit={handleSubmit} className={classes.form}>
<TextField
variant="outlined"
margin="normal"
fullWidth
id="website"
type="website"
label="Website"
name="website"
autoComplete="website"
value={formData.website}
onChange={handleInputChange('website')}
/>
<TextField
variant="outlined"
margin="normal"
fullWidth
id="cohort"
type="number"
inputProps={inputProps}
label="Cohort #"
name="cohort"
autoComplete="cohort"
helperText={errors.cohort}
error={errors.cohort ? true : false}
value={formData.cohort}
onChange={handleInputChange('cohort')}
/>
<TextField
variant="outlined"
margin="normal"
fullWidth
id="linkedIn"
type="linkedIn"
label="LinkedIn"
name="linkedIn"
autoComplete="linkedIn"
value={formData.linkedIn}
onChange={handleInputChange('linkedIn')}
/>
<TextField
variant="outlined"
margin="normal"
fullWidth
id="github"
type="github"
label="GitHub"
name="github"
autoComplete="github"
value={formData.github}
onChange={handleInputChange('github')}
/>
<TextField
variant="outlined"
margin="normal"
fullWidth
id="program"
type="program"
label="Program"
name="program"
helperText={errors.program}
error={errors.program ? true : false}
autoComplete="program"
value={formData.program}
onChange={handleInputChange('program')}
/>
{errors.general && (
<Typography variant="body2" className={classes.customError}>
{errors.general}
</Typography>
)}
<Button
type="submit"
fullWidth
variant="contained"
color="primary"
className={classes.submit}
disabled={isInvalid}
>
Update User Info
{isloading && (
<CircularProgress size={30} className={classes.progress} />
)}
</Button>
</form>
</div>
<Box mt={8}>
<Copyright />
</Box>
</Container>
</div>
) : (
<CircularProgress size={60} className={classes.progressOne} />
)}
</>
)
}
export default Profile
I am fetching the token for my headers from local storage and trying to post the form data to my user endpoint. When I post, I get an error stating:
xhr.js:178 POST http://localhost:3000/[object%20Object] 404 (Not
Found)
I'm hitting the correct end point, but for some reason the post isn't hitting the /user endpoint with my form data. any insight would be awesome.

Resources