This form is used to edit a user profile. It should load with up to date user data for the initial values. To handle this, I've added a redux fetchUser action in useEffect and set the initial values of the form to the currentUser in the redux store. fetchUser hits a database endpoint and updates the currentUser in the redux store.
However, if I submit the form and reload the page, the initial data is not updated.
I'm not sure why my initial values/form is not up to date with my redux store. The form will update with the right data if I navigate away from it and navigate back to it twice.
My assumption is that the form is not resetting the initial value each time the ponent is rendering. It looks like that data is persisting. I have tried passing in an object to resetForm() to force the initial values to update, but this results in the same issue. If
Here is the full react ponent:
import { Formik, Form, Field, ErrorMessage } from "formik"
//redux action that fetches current user
import { fetchUser } from "../../actions"
import { connect } from "react-redux"
import profileSchema from "./yupSchema"
import updateProfile from "./updateAxiosCall"
const submitData = (data, resetForm, tagNames) => {
const newProfile = { ...data}
//end point call - working as intended
updateProfile(newProfile)
resetForm()
}
const ProfileForm = ({ currentUser, fetchUser }) => {
const [formData, setFormData] = useState(null)
useEffect(() => {
//grab user on ponent render
fetchUser()
setFormData({
linkedin: currentUser.linkedin,
github: currentUser.github,
instagram: currentUser.instagram,
facebook: currentUser.facebook,
twitter: currentUser.twitter,
header: currentUser.header,
bio: currentUser.bio,
})
}, [])
if (formData === null) {
return <div>Not ready</div>
} else {
return (
<Formik
initialValues={formData}
validationSchema={profileSchema}
onSubmit={(values, { resetForm }) => {
submitData(values, resetForm, tagNames)
}}
>
{({ errors, resetForm, handleChange, touched, values, onSubmit }) => (
<Form
style={{
display: "flex",
flexDirection: "column",
width: "100%",
}}
autoComplete="off"
>
//This is up to date
<h1>{currentUser.header}</h1>
<TextField
error={errors.header && touched.header}
onChange={handleChange}
name="header"
variant="outlined"
value={values.header || ""}
id="header"
margin="normal"
label="header"
helperText={
errors.header && touched.header ? errors.header : null
}
/>
{/* ...additional <TextField> ponents */}
<Button
style={{ margin: "10px 0px" }}
size="large"
margin="normal"
type="submit"
variant="contained"
color="primary"
>
Save
</Button>
</Form>
)}
</Formik>
)
}
}
function mapStateToProps(state) {
return {
currentUser: state.currentUser,
}
}
export default connect(mapStateToProps, { fetchUser })(ProfileForm)
This form is used to edit a user profile. It should load with up to date user data for the initial values. To handle this, I've added a redux fetchUser action in useEffect and set the initial values of the form to the currentUser in the redux store. fetchUser hits a database endpoint and updates the currentUser in the redux store.
However, if I submit the form and reload the page, the initial data is not updated.
I'm not sure why my initial values/form is not up to date with my redux store. The form will update with the right data if I navigate away from it and navigate back to it twice.
My assumption is that the form is not resetting the initial value each time the ponent is rendering. It looks like that data is persisting. I have tried passing in an object to resetForm() to force the initial values to update, but this results in the same issue. If
Here is the full react ponent:
import { Formik, Form, Field, ErrorMessage } from "formik"
//redux action that fetches current user
import { fetchUser } from "../../actions"
import { connect } from "react-redux"
import profileSchema from "./yupSchema"
import updateProfile from "./updateAxiosCall"
const submitData = (data, resetForm, tagNames) => {
const newProfile = { ...data}
//end point call - working as intended
updateProfile(newProfile)
resetForm()
}
const ProfileForm = ({ currentUser, fetchUser }) => {
const [formData, setFormData] = useState(null)
useEffect(() => {
//grab user on ponent render
fetchUser()
setFormData({
linkedin: currentUser.linkedin,
github: currentUser.github,
instagram: currentUser.instagram,
facebook: currentUser.facebook,
twitter: currentUser.twitter,
header: currentUser.header,
bio: currentUser.bio,
})
}, [])
if (formData === null) {
return <div>Not ready</div>
} else {
return (
<Formik
initialValues={formData}
validationSchema={profileSchema}
onSubmit={(values, { resetForm }) => {
submitData(values, resetForm, tagNames)
}}
>
{({ errors, resetForm, handleChange, touched, values, onSubmit }) => (
<Form
style={{
display: "flex",
flexDirection: "column",
width: "100%",
}}
autoComplete="off"
>
//This is up to date
<h1>{currentUser.header}</h1>
<TextField
error={errors.header && touched.header}
onChange={handleChange}
name="header"
variant="outlined"
value={values.header || ""}
id="header"
margin="normal"
label="header"
helperText={
errors.header && touched.header ? errors.header : null
}
/>
{/* ...additional <TextField> ponents */}
<Button
style={{ margin: "10px 0px" }}
size="large"
margin="normal"
type="submit"
variant="contained"
color="primary"
>
Save
</Button>
</Form>
)}
</Formik>
)
}
}
function mapStateToProps(state) {
return {
currentUser: state.currentUser,
}
}
export default connect(mapStateToProps, { fetchUser })(ProfileForm)
Share
Improve this question
asked Jun 14, 2020 at 19:15
WriterStateWriterState
3694 silver badges20 bronze badges
3 Answers
Reset to default 11put enableReinitialize={true}
as a Formik property.
so this:
<Formik
enableReinitialize={true}
initialValues={formData}
...
@Jared answer works for me by using enableReinitialize:true hook
const formik = useFormik({
initialValues: {
title: "",
text: "",
authorid: `${user.id}`,
cat_id: '1',
},
validateOnBlur: true,
onSubmit,
enableReinitialize: true,
});
You might need to separate your useEffect
hook into 2 useEffect
s. One hook for the "ponentDidMount" cycle (e.g. []
) and another watching changes to currentUser
.
Example:
const [formData, setFormData] = useState(null)
useEffect(() => {
//grab user on ponent render
fetchUser()
}, [])
useEffect(() => {
setFormData({
linkedin: currentUser.linkedin,
github: currentUser.github,
instagram: currentUser.instagram,
facebook: currentUser.facebook,
twitter: currentUser.twitter,
header: currentUser.header,
bio: currentUser.bio,
})
}, [ currentUser ])