Usman
Usman

Reputation: 37

Input form value remains the same even with an onChange handler

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

Answers (2)

Mario Vernari
Mario Vernari

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

Ibrahim Adeniyi
Ibrahim Adeniyi

Reputation: 11

  1. Your form inputs values should be targetting userData instead of user i.e
<input 
    ...name="name"
    value={userData.name} />
  1. You need to set your userData in the useEffect method as it seems that for each user, the userData value is using values fetched previously.
     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

Related Questions