I am trying to make a personal page with the name and other info and when you click EDIT PROFILE button it will take you to another page to edit the information.
On the EDIT Profile page I have the information on the input form that you can input new info. I want it to reflect the change only when I click the SAVE button. If I don't click the SAVE button and just click X button instead, it's not supposed to change when I go back the Profile page.
I am not sure what I did wrong but right now, it changes whether I clicked the SAVE button or not. Can someone please help me figure out what I did wrong? I've been at this for hours and I still can't figure out where I went wrong.
Below are my code:
profile-reducers.js
const profileReducer = (state = profile, action) => {
switch (action.type) {
case 'edit-profile':
state[0].name = action.name;
return state;
default:
return state;
}
}
export default profileReducer;
edit-profile.js
const EditProfileItem = () => {
let profile = useSelector(state => state.profile[0]);
const [name, setname] = useState(profile.name);
const dispatch = useDispatch();
const editProfileClickHandler = () => {
dispatch({
type: 'edit-profile',
name: name,
});
}
return (
<>
<div className = 'row p-2'>
<div className = 'float-start col-1'>
<Link to='/tuiter/profile'>
<i className = 'fas fa-times icon' style={{color:'black'}}/>
</Link>
</div>
<div className='col-5 text-black fw-bold'>
Edit Profile
</div>
<div className = 'col-6'>
<Link
className='btn rounded-pill bg-black float-end text-white fw-bold'
to='/tuiter/profile'
onClick={editProfileClickHandler()}
> Save
</Link>
</div>
</div>
<div className = 'pt-3'>
<ul className='list-group'>
<li className='list-group-item'>
<label className='text-secondary'>Name</label>
<input
className='form-control border-0 p-0'
defaultValue={profile.name}
onChange={(event) => setname(event.target.value)}/>
</li>
</ul>
</div>
</>
};
export default EditProfileItem;
CodePudding user response:
Issues
The
EditProfileItem
is rendering a link where theonClick
handler's callback is immediately invoked when the component renders. It should be passed as a callback to be called later when actually clicked.onClick={editProfileClickHandler}
instead ofonClick={editProfileClickHandler()}
The
profileReducer
should mutate state or return a new state value, but not both.The
input
should be fully controlled using thename
state and thevalue
prop instead of thedefaultValue
prop.
Solution
const EditProfileItem = () => {
const profile = useSelector(state => state.profile[0]);
const [name, setName] = useState(profile.name);
const dispatch = useDispatch();
const editProfileClickHandler = () => {
dispatch({
type: 'edit-profile',
payload: name,
});
};
return (
<>
<div className='row p-2'>
<div className='float-start col-1'>
<Link to='/tuiter/profile'>
<i className='fas fa-times icon' style={{ color: 'black' }} />
</Link>
</div>
<div className='col-5 text-black fw-bold'>
Edit Profile
</div>
<div className='col-6'>
<Link
className='btn rounded-pill bg-black float-end text-white fw-bold'
to='/tuiter/profile'
onClick={editProfileClickHandler} // <-- pass callback reference
>
Save
</Link>
</div>
</div>
<div className = 'pt-3'>
<ul className='list-group'>
<li className='list-group-item'>
<label className='text-secondary'>Name</label>
<input
className='form-control border-0 p-0'
value={name} // <-- use value prop
onChange={(event) => setName(event.target.value)}
/>
</li>
</ul>
</div>
</>
);
};
profileReducer
Since this doesn't appear to be a redux-toolkit slice reducer I'll assume it is a legacy redux reducer function. The previous state should be shallow copied, and then the appropriate property updated.
const profileReducer = (state = profile, action) => {
switch (action.type) {
case 'edit-profile':
const nextState = state.slice();
nextState[0] = {
...nextState[0],
name: action.payload
};
return nextState;
default:
return state;
}
};
CodePudding user response:
onClick={editProfileClickHandler()}
This particular line, you're calling the function on every render, you need to pass a function into an onClick handler, and not the return of a function
it should be onClick={()=> editProfileClickHandler()}
here a function is being passed into the onClick, which would be called when there is a click event
i hope this helps