Reputation: 37
This code is a functional component that should render a user detail page(Show details view) OR a form to edit(Edit detail view) this user info depending on the state of isUpdate. This works alright, as the update and save buttons change the state of isUpdate to render the Edit View or Show View respectively.
When I select a user, the page gets the specific user by match.params.id which also works. My problem is when the isUpdate is set to true (the edit form with the original values of the user details is rendered) I expect that the input values change when I type on the input for, but instead the value remains the same as its original value(unable to type new values). I dont know why I am facing this problem.
UserDetail Component code below:
import React, {Fragment, useEffect, useState} from 'react';
import { connect } from 'react-redux';
import { findUser } from '../../actions/user';
const UserDetails =({match, user, loading, findUser}) => {
const[isUpdate, setIsUpdate]=useState(false);
//fetching user info based on the params id
useEffect(() => {
findUser(match.params.id);
},[])
//setting the initial state of user to the values from the fetched data
const[userData, setUserData]=useState({
name: user.name,
email: user.email,
});
//on Change handler
const onChange = e =>{
setUserData({...userData, [e.target.name]:e.target.value})
}
//User detail rendered to be viewed or edited
return loading ?
(<Fragment>
<div className="loader-container" ></div>
<div className="loader"></div>
</Fragment>) :
(isUpdate ? (
<Fragment>
<div className="detail-container">
<form>
<div className="form-row">
<div className="form-group col-md-6">
<label htmlFor="name">Full Name:</label>
<input
type="name"
className="form-control"
id="name"
name="name"
value={user.name}
onChange={e=>onChange(e)}/>
</div>
<div className="form-group col-md-6">
<label htmlFor="email">Email:</label>
<input
type="email"
className="form-control"
id="email"
name="email"
value={user.email}
onChange={e=>onChange(e)}/>
</div>
</div>
<button type="submit" className="btn btn-primary" onClick={()=>setIsUpdate(false)}>SAVE</button>
</form>
</div>
</Fragment>):
(<Fragment>
<div className="detail-container">
<div className="d-flex justify-content-end mb-20"> <button className="btn btn-warning "
onClick={()=>setIsUpdate(true)}> UPDATE</button>
</div>
<div className="row mb-10">
<div className=" col-md-6">
<div className="detail-label">Full Name:</div>
<div className="detail">{`${user.name}`}</div>
</div>
<div className=" col-md-6">
<div className="detail-label">Email:</div>
<div className="detail">{`${user.email}`}</div>
</div>
</div>
</div>
</Fragment>))
const mapStateToProps = (state) => ({
user: state.user.a_user,
loading: state.user.loading
})
export default connect(mapStateToProps,{findUser})(UserDetails);
Please I would appreciate anyone pointing me in the right direction.
Upvotes: 0
Views: 663
Reputation: 7306
The user
data remains constant during the editing session, so the input
element cannot work properly. Try to change its declaration using the userData
instead:
<input
type="name"
className="form-control"
id="name"
name="name"
value={userData.name}
onChange={e=>onChange(e)}/>
UPDATE: in order to update the userData
state whenever the user
changes, you could use this trick:
const[userData, setUserData]=useState();
useEffect(
() => {
setUserData({
name: user.name,
email: user.email,
});
},
[user]
);
Take care to handle the initial condition where userData
is undefined.
Upvotes: 1
Reputation: 11
<input
...name="name"
value={userData.name} />
useEffect(() => {
findUser(match.params.id)
setUserData(user)
},[])
I'm guessing the findUser method updates the user in the parent component. This should work.
Upvotes: 0