I Am populating values of my input field from JSON data what am getting from back-end, now there is an edit button on UI by on click on that button I am enabling my input field but not able to type inside as I am setting some value
I want to write inside the input once I have made them editable.
const { register, handleSubmit, errors } = useForm();
const [disabled, setdisabled] = useState(false);
const [editBtn, seteditBtn] = useState(true);
<form onSubmit={handleSubmit(onSubmit)}>
{editBtn === true && (
<div align="right">
<button
className="btn white_color_btn"
type="button"
onClick={edit}
>
Edit
</button>
</div>
)}
{editBtn === false && (
<button className="btn white_color_btn" type="submit">
Save
</button>
)}
<div className="row">
<div className="form-group col-6 col-sm-6 col-md-6 col-lg-4 col-xl-4">
<input
type="text"
disable
id="firstName"
name="firstName"
value={dataItems.firstname}
disabled={disabled ? "" : "disabled"}
ref={register({ required: true })}
/>
{errors.firstname && (
<span className="text-danger">first name required</span>
)}
<br />
<label htmlFor="emp_designation">First name</label>
</div>
<div className="form-group col-6 col-sm-6 col-md-6 col-lg-4 col-xl-4">
<input
type="text"
disabled
id="lastname"
name="lastname"
value={dataItems.lastname}
disabled={disabled ? "" : "disabled"}
ref={register({ required: true })}
/>
{errors.lastname && (
<span className="text-danger">last name required</span>
)}
<br />
<label htmlFor="lastname">Lastname</label>
</div>
</div>
</form>
On click of edit
const edit = () => {
setdisabled(true);
};
Code sandbox
You need to make your input as a controlled component and write onChange handlers which will update the state. This will allow you to edit the input field values. Demo
const [disabled, setdisabled] = useState(false);
const [name, setName] = useState(empData.item.name) // setting default name
const [lastname, setLastname] = useState(empData.item.lastname) // default lastname
const edit = () => {
setdisabled(true);
};
return (<div className="container-fluid">
<div align="right">
<button className="btn" onClick={edit}>
Edit
</button>
</div>
<div className="row">
<div>
<input
type="text"
disable
id="item.value"
value={name}
onChange={(e) => {
setName(e.target.value)
}}
disabled={disabled ? "" : "disabled"}
/>
<br />
<label htmlFor="name">Name</label>
</div>
<div>
<input
type="text"
disabled
id={"lastname"}
value={lastname}
onChange={(e) => {
setLastname(e.target.value)
}}
disabled={disabled ? "" : "disabled"}
/>
<br />
<label htmlFor="lastname">Lastname</label>
</div>
</div>
</div>);
Your input is controlled by the value you are giving to it. ie: Its value is always for example empData.item.name.
And you are not providing a change handler to handle the change.
Try adding something like this:
function myChangeHandler(e){
setEditedValueSomeHow(e.target.value);
}
<input
// ...
onChange={myChangeHandler}
/>
Read more about uncontrolled components
PS: you should have had a warning message in your console like this one:
Edit:
You are using react-hook-form to manage your form but at the same time giving values to your inputs.
Please refer to this link to initialize your form values.
short story:
Remove value form your input.
Pass an object to useForm hook containing initial values.
const { register, handleSubmit, errors } = useForm({
defaultValues: {
firstName: "steve",
lastname: "smith"
}
});
Here is a working fork for your codesandbox
In order to make the input editable, you need to update a local state which controlls the input value. As suggested by you in the comments, you are using graphql to get the data, you can make use of useEffect to set the data in state and then on click of edit, update the localState
export default function App() {
const { register, handleSubmit, errors } = useForm();
const [disabled, setdisabled] = useState(true);
const [editBtn, seteditBtn] = useState(true);
const { loading, data } = useQuery("some qraphql query here"); // getting data from graphql
const [formData, setFormData] = useState({});
useEffect(() => {
setFormData(data);
}, [data]);
const edit = () => {
setdisabled(false);
seteditBtn(false);
};
const onSubmit = () => {
console.log(formData);
// submit data using formData state.
};
const handleChange = e => {
const name = e.target.name;
const value = e.target.value;
console.log(name, value);
setFormData(prev => ({ ...prev, [name]: value }));
};
return (
<div className="container-fluid">
<form onSubmit={handleSubmit(onSubmit)}>
{editBtn === true && (
<div align="right">
<button
className="btn white_color_btn"
type="button"
onClick={edit}
>
Edit
</button>
</div>
)}
{editBtn === false && (
<button className="btn white_color_btn" type="submit">
Save
</button>
)}
<div className="row">
<div className="form-group col-6 col-sm-6 col-md-6 col-lg-4 col-xl-4">
<input
type="text"
id="firstname"
name="firstname"
onChange={handleChange}
value={formData.firstname}
disabled={disabled}
ref={register({ required: true })}
/>
{errors.firstname && (
<span className="text-danger">first name required</span>
)}
<br />
<label htmlFor="emp_designation">First name</label>
</div>
<div className="form-group col-6 col-sm-6 col-md-6 col-lg-4 col-xl-4">
<input
type="text"
id="lastname"
name="lastname"
value={formData.lastname}
onChange={handleChange}
disabled={disabled}
ref={register({ required: true })}
/>
{errors.lastname && (
<span className="text-danger">last name required</span>
)}
<br />
<label htmlFor="lastname">Lastname</label>
</div>
</div>
</form>
</div>
);
}
Working mock demo
Related
I am trying to fetch the user based on their id but can't sometimes I get the user but it is like the state is preserving the values if I try to get another user value but I still saw the previous user data. Hey anyone please help me I am stuck here for hours now.
here is the image of my users list
here is an update
I went to my network tab and saw that
I get the user Based on their users but I see the value in fields until I click on my first user in the shown list which is shown in fields then again If click the next user I still see the first user details so it definitely not API issue in my state problem please help me to fix this.
EditUser.tsx
const UpdateUser = ({ setUsers, id }) => {
const animatedComponents = makeAnimated();
const [rolesData, setRolesData] = useState([]);
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const [role, setRole] = useState("");
const [job_preference, setJobPreference] =
useState([]);
const [multiSelect, setMultiSelect] = useState(
[]
);
const fetchDataBasedOnID = async (id) => {
const { data } = await axios.get(
`/api/user/${id}`
);
getDataOfMultiSelect(data);
};
const getDataOfMultiSelect = (data) => {
const result = states.filter((state) =>
data.job_preference.includes(state.value)
);
setMultiSelect(result);
setName(data.name);
setEmail(data.email);
setRole(data.role);
};
const resetFields = () => {
setName("");
setEmail("");
setMultiSelect("");
setRole("");
};
useEffect(() => {
handleRoles();
}, []);
const handleSubmit = async (e) => {
e.preventDefault();
const { data } = await axios.put(
`/api/user/${id}`,
{
name,
email,
role,
job_preference,
}
);
toast.success("User updated successfully");
usersList();
resetFields();
};
return (
<>
{/* Button trigger modal */}
<div>
<button
type='button'
onClick={() => fetchDataBasedOnID(id)}
className='btn btn-warning'
data-bs-toggle='modal'
data-bs-target='#updateModal'>
<BiEdit />
</button>
</div>
{/* Modal */}
<div
className='modal fade'
id='updateModal'
tabIndex='-1'
aria-hidden='true'>
<div className='modal-dialog modal-dialog-centered'>
<div className='modal-content'>
<div className='modal-header'>
<h1
className='modal-title fs-5'
id='exampleModalLabel'>
Update User
</h1>
<button
type='button'
className='btn-close'
data-bs-dismiss='modal'
aria-label='Close'></button>
</div>
<form onSubmit={handleSubmit}>
<div className='modal-body'>
<div className='mb-3'>
<label className='form-label'>
Name
</label>
<input
type='text'
value={name}
onChange={(e) =>
setName(e.target.value)
}
required
className='form-control'
placeholder='John Doe'
/>
</div>
<div className='mb-3'>
<label className='form-label'>
Email address
</label>
<input
type='email'
value={email}
required
onChange={(e) =>
setEmail(e.target.value)
}
className='form-control'
placeholder='name#example.com'
/>
</div>
<div className='mb-3'>
<label className='form-label'>
Role
</label>
<select
className='form-select option'
value={role}
onChange={handleRoleChange}>
<option className='option'>
Select a Role
</option>
{rolesData?.map(
({ _id, role_name }) => (
<option
className='option'
key={_id}
value={role_name}>
{role_name}
</option>
)
)}
</select>
</div>
<div className='mb-3'>
<label className='form-label'>
Job Preference
</label>
<Select
value={multiSelect}
isMulti
components={
animatedComponents
}
isSearchable
placeholder='Choose any 3 states as job location'
options={states}
onChange={
handleMultiSelectChange
}
isOptionDisabled={() =>
multiSelect.length >= 3
}
/>
</div>
</div>
<div className='modal-footer'>
<button
type='button'
className='btn btn-secondary'
data-bs-dismiss='modal'>
Close
</button>
<button
type='submit'
className='btn btn-success'
data-bs-dismiss='modal'>
Save Changes
</button>
</div>
</form>
</div>
</div>
</div>
</>
);
};
export default UpdateUser;
I am trying to create a Form validation for 4 inputs, companyName - email - name - phone.
My aim is to validate them using regular expression and won't allow the user to press submit unless the inputs aregood to go.
Problem :
I set the logic testing just two validations so far, the company name and the email.
When I press sometimes submit, it ignores the validation and sometimes not.
Please help me to let them work properly.
import { React, useState, useEffect } from "react";
/*
*****
*****
Import Showcase.scss -
*/
import "./Showcase.scss";
const Showacase = () => {
/*
*****
*****
Logic Goes Here
*/
//State Management
//Company State
const [company, setCompany] = useState();
const [companyValue, setCompanyValue] = useState();
//name State
const [name, setName] = useState();
const [nameValue, setNameValue] = useState();
//Phone State
const [phone, setPhone] = useState();
const [phoneValue, setPhoneValue] = useState();
//Email State
const [email, setEmail] = useState();
const [emailValue, setEmailValue] = useState();
//Hide Inputs
const [input, setInput] = useState(true);
// Message State
const [message, setMessage] = useState(true);
// SubMessage
const [subMessage, setSubMessage] = useState(true);
//InsertLine
const [line, setLine] = useState(false);
//Hide Button
const [btn, setBtn] = useState(true);
/* Validation State */
const [emailValidate, setEmailValidate] = useState(false);
/* Validation State */
const [companyValidate, setCompanyValidate] = useState(false);
// OnSubmit
const onSubmit = (e) => {
e.preventDefault();
};
//onChange Company
const onChangeCompany = (e) => {
setCompany(e.target.value);
};
//OnClick
const onClick = (e) => {
// Company and Name
const reCompanyName = /^[a-zA-Z]{2,12}$/;
// Email Address
const reEmail =
/^([a-zA-Z0-9_\-\.]+)#([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5})$/;
if (!reCompanyName.test(company)) {
setCompanyValidate(true);
return;
}
if (!reEmail.test(email)) {
setEmailValidate(true);
return;
}
//upComing Phone
if (company === "" || phone === "" || email === "" || name === "") {
return;
} else {
/* setting the New Values */
setCompanyValue(company);
setNameValue(name);
setPhoneValue(phone);
setEmailValue(email);
/* Clearing the Inputs */
setCompany("");
setName("");
setPhone("");
setEmail("");
/* Logic of hidding Items */
setInput(false);
setMessage(false);
setSubMessage(false);
setLine(true);
setBtn(false);
/* Reset all options after submission after 5 seconds */
setTimeout(() => {
setInput(!false);
setMessage(!false);
setSubMessage(!false);
setLine(!true);
setBtn(!false);
}, 5000);
}
};
return (
<>
{/* Showcase Main */}
<div className="Showcase">
<div className="Container">
{/* Showcase Main / Applying the flex */}
<div className="Showcase__inside">
{/* Right Side / form and logic */}
<div className="Showcase__inside--left">
<div className="Showcase__inside--left--box">
{/* the Top Message */}
{message ? (
<h1>Find inbound call centers for your company</h1>
) : (
<h1>Thank you for your request!</h1>
)}
{/* the sub Message Message */}
{subMessage ? (
<p>
Use our AI and Big Data driven call center sourcing solution
</p>
) : (
<p className="paragraphAfterSubmission">
You’ve taken the first step. Our experts will get in touch
with you soon.
</p>
)}
{/* Inserting the Line */}
{line ? <hr></hr> : null}
<form onSubmit={onSubmit}>
{/* Company */}
<div className="Showcase__inside--left--box--form">
<label for="company">Company </label>
{input ? (
<div>
<input
required
value={company}
onChange={onChangeCompany}
type="text"
id="company"
placeholder="Company"
name="company"
/>
{companyValidate ? (
<div className="companyValidate">
<small>Please Provide a valid Company Name</small>
</div>
) : (
""
)}
</div>
) : (
<p>{companyValue}</p>
)}
</div>
{/* Name */}
<div className="Showcase__inside--left--box--form">
<label for="Name">Name </label>
{input ? (
<input
required
onChange={(e) => setName(e.target.value)}
value={name}
type="text"
id="Name"
placeholder="Full name"
name="Name"
/>
) : (
<p>{nameValue}</p>
)}
</div>
{/* Phone */}
<div className="Showcase__inside--left--box--form">
<label for="Phone">Phone </label>
{input ? (
<input
required
onChange={(e) => setPhone(e.target.value)}
value={phone}
type="text"
id="Phone"
placeholder="+49"
name="phone"
/>
) : (
<p>{phoneValue}</p>
)}
</div>
{/* Email */}
<div className="Showcase__inside--left--box--form">
<label for="Email">Email </label>
{input ? (
<div>
<input
required
onChange={(e) => setEmail(e.target.value)}
value={email}
type="email"
id="Email"
placeholder="name#mail.com"
name="email"
/>
{emailValidate ? (
<div className="EmailValidate">
<small>Please Provide a valid Email</small>
</div>
) : (
""
)}
</div>
) : (
<p>{emailValue}</p>
)}
</div>
{/* Submit */}
<div className="Showcase__inside--left--box--form">
<div className="Showcase__inside--left--box--form--submit">
{/* OnClick Method */}
{btn ? (
<button onClick={onClick} type="submit">
Get informed
</button>
) : null}
</div>
</div>
</form>
</div>
</div>
{/* Right SIDE %s */}
<div className="Showcase__inside--right">
<div>
<div>
<h1>Welcome to Europe’s largest call center database </h1>
</div>
<div className="Showcase__inside--right--per">
<div className="Showcase__inside--right--per--single">
<small>500+</small>
<h1>Tenders</h1>
</div>
<div className="Showcase__inside--right--per--single">
<small>200+</small>
<h1>Callcenter</h1>
</div>
<div className="Showcase__inside--right--per--single">
<small>375.000</small>
<h1>Agents available</h1>
</div>
<div className="Showcase__inside--right--per--single">
<small>85%</small>
<h1>Faster sourcing</h1>
</div>
</div>
</div>
</div>
{/* Right Ended %s */}
</div>
</div>
</div>
</>
);
};
export default Showacase;
My code has got 3 input fields i.e first name, last name, email and 1 useState to hold its value, I want to remove the div part containing all the input fields after i hit Sign up and display only Thank You
My code has got 3 input fields i.e first name, last name, email and 1 useState to hold its value, I want to remove the div part containing all the input fields after i hit Sign up and display only Thank You
Before signing up
AFter signing up
const Home = () => {
const [saveInput, setInput] = useState({
fname: '',
lname: '',
email: '',
});
const [message, setMessage] = useState('enter email');
const inputFields = (event) => {
const { value, name } = event.target;
setInput((preValue) => ({
...preValue,
[name]: value,
}));
};
const onSubmits = (event) => {
setMessage('thanks');
};
return (
<div className="homeMain">
<div className="row">
<img
className="home_img"
src="https://i.pinimg.com/originals/53/b5/d7/53b5d70023efa05ec6797b25df413b73.jpg"
/>
<h1 className="home_h1 text-center">Maryam's Restaurant</h1>
<Link
style={{
color: 'white',
textDecoration: 'inherit',
textAlign: 'center',
}}
to="/Restaurant"
className="home_button"
>
View Menu
</Link>
<h2 className="home_h2 text-center">
Binging with Babish is a cooking show dedicated to discovering what
the delectable (and occasionally horrible) foods from fiction actually
taste like.
</h2>
{receipeList.map((curElem) => (
<div className="home2Main">
<img className="home_img2" src={curElem.img} />
<p className="home2Mainp1">{curElem.h1}</p>
<p className="home2Mainp2">{curElem.date}</p>
</div>
))}
</div>
<homeMainDetails />
<div className="home4Main">
<h4>
<bold>Subscribe</bold>
<br />
<small>
Sign up with your email address to receive news and updates.
</small>
</h4>
<input
className="home4MainInput"
name="fname"
onChange={inputFields}
value={saveInput.fname}
type="text"
placeholder="First Name"
/>
<input
className="home4MainInput"
name="lname"
onChange={inputFields}
value={saveInput.lname}
type="text"
placeholder="Last Name"
/>
<input
className="home4MainInput"
name="email"
onChange={inputFields}
value={saveInput.email}
type="text"
placeholder="Email Address"
/>
<button onClick={onSubmits}>Sign Up</button>
<h4 className="home4Mainh4">
<small>{message}</small>
</h4>
</div>
</div>
);
};
export default Home;
You could use another state to indicate your submit state.
This way you can hold state value without affecting to the message state:
Use another state:
const [isSubmited, setIsSubmited] = useState(false);
Change that state when you submit:
const onSubmits = (event) => {
setMessage('thanks');
setIsSubmited(true);
};
Then render it conditionally:
{isSubmited ? (
<div className="home4Main">
...
</div>
) : message}
You can do it with a basic condition message !== "Thank you" like this:
<div className="home4Main">
{message !== "Thank you" && (
<>
<h4>
<bold>Subscribe</bold>
<br />
<small>Sign up with your email address to receive news and updates.</small>
</h4>
<input
className="home4MainInput"
name="fname"
onChange={inputFields}
value={saveInput.fname}
type="text"
placeholder="First Name"
/>
<input
className="home4MainInput"
name="lname"
onChange={inputFields}
value={saveInput.lname}
type="text"
placeholder="Last Name"
/>
<input
className="home4MainInput"
name="email"
onChange={inputFields}
value={saveInput.email}
type="text"
placeholder="Email Address"
/>
<button onClick={onSubmits}>Sign Up</button>
</>
)}
<h4 className="home4Mainh4">
<small>{message}</small>
</h4>
</div>
And update message
const onSubmits = (event) => {
setMessage('Thank you');
};
Create a useState that contains the value on the state of the form.
const [isSubmited, setIsSubmited] = useState(false);
Then use this value in the JSX to conditional render the elements you want to display.
isSubmitted ? <div> Thank You! </div> : <div> your form.... </div>
You can call setIsSubmited(true) when you submit the form.
I am trying to get updated textbox value if I have props from parent component.
Here is my code -
const initialState = {
name: "",
age: 0
}
const UserAdd = (props:any) => {
const {selectedUser} = props;
const [state, setState] = useState<any>(initialState);
const dispatch = useDispatch();
const onChangeValue = (event:any) => {
const { name, value } = event.target;
setState((prevState:any) => (
{ ...prevState, [name]: value }
));
}
const onSubmit = (e:any) => {
e.preventDefault();
const { name } = e.target;
dispatch(addUser(state.name, state.age))
setState({ ...initialState });
}
const onUpdate = (e:any) => {
e.preventDefault();
const { name } = e.target;
console.log(state.name , state.age , "name-age")
}
return (
<div className="add-user">
<hr />
<h2>Add User</h2>
<hr />
{ selectedUser ?
(<form className="form-inline">
<input type="text" className="form-control mb-2 mr-sm-5 col-md-4" id="email2" placeholder="Enter user name" name="name" value={selectedUser.name} onChange={onChangeValue} />
<input type="text" className="form-control mb-2 mr-sm-5 col-md-4" id="pwd2" placeholder="Enter user age" name="age" onChange={onChangeValue} value={selectedUser.age} />
<button type="submit" onClick={onUpdate} className="btn btn-primary col-md-2 mb-2">Update</button>
</form>)
:
(
<form className="form-inline">
<input type="text" className="form-control mb-2 mr-sm-5 col-md-4" id="email2" placeholder="Enter user name" name="name" value={state.name} onChange={onChangeValue} />
<input type="text" className="form-control mb-2 mr-sm-5 col-md-4" id="pwd2" placeholder="Enter user age" name="age" onChange={onChangeValue} value={state.age} />
<button type="submit" onClick={onSubmit} className="btn btn-primary col-md-2 mb-2">Submit</button>
</form>
)
}
</div>
)
}
export default UserAdd;
When There is no props i.e (no selectedUser), Then state change working fine and I am able to dispatch action as well. But When Props(selectedUser) is available, then I am unable to edit textbox field & unable to get updated state. Please someone help me.
look deeper into your code.. there is different forms when selectedUser is not falsy...
when there is selected user:
value={selectedUser.name}
shouled be like the other form's input:
value={state.name}
u also need to add useEffect to change the state when the prop is being changed, u can do it like so:
useEffect(()=>{
setState((prevState:any) => (
{ ...prevState, name: selectedUser.name}
));
},[selectedUser.name])
the useEffect then will be executed whenever any item of the dependency list will be different from the last render (in this case each time the selectedUser.name is being changed)
In case there is selectedUser, the value attribute of input field should be reactive. Currently, it is set to props that won't react to onChangeValue handler. Use state in the value attribute (state.name /state.age) and initialize states with selectedUser props value. It might look like below -
const initialState = {
name: "",
age: 0
}
const UserAdd = (props:any) => {
const {selectedUser} = props;
//Button text would be Update or submit that depends on selectedUser.
const btnText = selectedUser ? "Update" : "Submit";
//If it founds selected user then set to it otherwise go with initialState
const [state, setState] = useState<any>(selectedUser || initialState);
const dispatch = useDispatch();
const onChangeValue = (event:any) => {
const { name, value } = event.target;
setState((prevState:any) => (
{ ...prevState, [name]: value }
));
}
const onSubmit = (e:any) => {
e.preventDefault();
const { name } = e.target;
dispatch(addUser(state.name, state.age))
setState({ ...initialState });
}
return (
<div className="add-user">
<hr />
<h2>Add User</h2>
<hr />
<form className="form-inline">
<input type="text" className="form-control mb-2 mr-sm-5 col-md-4" id="email2" placeholder="Enter user name" name="name" value={selectedUser.name} onChange={onChangeValue} />
<input type="text" className="form-control mb-2 mr-sm-5 col-md-4" id="pwd2" placeholder="Enter user age" name="age" onChange={onChangeValue} value={selectedUser.age} />
<button type="submit" onClick={onUpdate} className="btn btn-primary col-md-2 mb-2">{btnText}</button>
</form>
</div>
)
}
export default UserAdd;
Once you set it up like this you don't need to render forms conditionally. you only need one form. I have added a few comments as well. I have created a working POC here https://codesandbox.io/s/propstostate-react-ssirn
My react form for updating profile data currently only interacts with firestore when all inputs have been changed.
Current Error;
TypeError: Cannot read property '0' of undefined" # profileActions.js:10:4
Things I have tried checked;
- Props dispatching to 'updateProfile' function - working
- Changing 'onChange' function to 'onSubmit' - didn't work
- Adding required to all input fields - didn't work
- Replacing defaultValue with placeholder - didn't work
Profile.js
import React, { Component } from "react";
import { connect } from "react-redux";
import { updateProfile } from "../../actions/profileActions";
import Password from "./Password";
import { Redirect } from "react-router-dom";
class Profile extends Component {
state = {
firstName: this.props.profile.firstName,
lastName: this.props.profile.lastName,
businessName: this.props.profile.businessName,
phoneNumber: this.props.profile.phoneNumber,
email: this.props.profile.email
};
handleChange = e => {
this.setState({
[e.target.id]: e.target.value
});
};
handleSubmit = e => {
e.preventDefault();
//console.log.apply(this.state);
this.props.updateProfile(this.state);
};
render() {
const { profile, profileError, auth } = this.props;
if (!auth.uid) return <Redirect to="/signin" />;
return (
<div className="container-fluid">
<form className="m-4" onSubmit={this.handleSubmit} to="/profile">
<div>{/* FIX - red line appears when bg-white removed below */}</div>
<div>
{/* FIX - form only submits correctly when all inputs have been changed */}
</div>
<div
className="alert-danger rounded col-xs-6 col-sm-6 col-md-6 col-lg-6 mx-auto bg-white"
style={{ color: "#ff0000" }}
>
{profileError ? <p>{profileError}</p> : null}
</div>
<div className="row">
<div className="col-xs-1 col-sm-1 col-md-1 col-lg-1" />
<div className="col-xs-3 col-sm-3 col-md-3 col-lg-3 d-flex flex-column mx-auto">
<div className="col-stretch rig-bot profile-label">
<h5 className="">First name :</h5>
</div>
<br />
<div className="col-stretch rig-bot profile-label">
<h5 className="">Last name :</h5>
</div>
<br />
<div className="col-stretch rig-bot profile-label">
<h5 className="">Business name :</h5>
</div>
<br />
<div className="col-stretch rig-bot profile-label">
<h5 className="">Phone number :</h5>
</div>
<br />
<div className="col-stretch rig-bot profile-label">
<h5 className="">Email :</h5>
</div>
<br />
</div>
<div className="col-xs-5 col-sm-5 col-md-5 col-lg-5 d-flex flex-column">
<div className="form-label-group">
<input
type="text"
id="firstName"
className="form-control"
defaultValue={profile.firstName}
autoFocus
onChange={this.handleChange}
/>
</div>
<br />
<div className="form-label-group">
<input
type="text"
id="lastName"
className="form-control"
defaultValue={profile.lastName}
onChange={this.handleChange}
/>
</div>
<br />
<div className="form-label-group">
<input
type="text"
id="businessName"
className="form-control"
defaultValue={profile.businessName}
onChange={this.handleChange}
/>
</div>
<br />
<div className="form-label-group">
<input
type="tel"
id="phoneNumber"
className="form-control"
defaultValue={profile.phoneNumber}
onChange={this.handleChange}
/>
</div>
<br />
<div className="form-label-group">
<input
type="email"
id="email"
className="form-control"
defaultValue={profile.email}
onChange={this.handleChange}
/>
</div>
<br />
</div>
<div className="col-xs-3 col-sm-3 col-md-3 col-lg-3" />
</div>
<div className="row">
<div className="col-xs-4 col-sm-4 col-md-4 col-lg-4 p-4 cen-mid mx-auto">
<input
className="btn btn-lg btn-primary btn-md"
type="submit"
value="Submit"
/>
</div>
</div>
</form>
<Password />
<div className="y-100" />
</div>
);
}
}
const mapStateToProps = state => {
console.log(state);
return {
profile: state.firebase.profile,
profileError: state.profile.profileError,
auth: state.firebase.auth
};
};
const mapDispatchToProps = dispatch => {
return {
updateProfile: profile => dispatch(updateProfile(profile))
};
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(Profile);
profileActions.js
export const updateProfile = props => {
return (dispatch, getState, { getFirebase, getFirestore }) => {
const firestore = getFirestore();
const userId = getState().firebase.auth.uid;
const firstName = props.firstName;
const lastName = props.lastName;
const initials = props.firstName[0] + props.lastName[0];
const businessName = props.businessName;
const phoneNumber = props.phoneNumber;
const email = props.email;
firestore
.collection("users")
.doc(userId)
.update({
firstName: firstName,
lastName: lastName,
initials: initials,
businessName: businessName,
phoneNumber: phoneNumber,
email: email
})
.then(
firestore.collection("auditProfile").add({
userId: userId,
action: "update",
firstName: firstName,
lastName: lastName,
businessName: businessName,
phoneNumber: phoneNumber,
email: email,
changedOn: new Date()
})
)
.then(() => {
dispatch({ type: "UPDATE_PROFILE" });
})
.catch(err => {
dispatch({ type: "UPDATE_PROFILE_ERROR", err });
});
};
};
I currently have no rules attached to my firestore database and am really hoping the solution is something super stupid like; "firestore won't allow you to use update function if fieldValues are identical".
My brain has currently turned to mush so have given up. Please help?
Thanks in advance for anyone who gives this any time :)
One thing to point out is that you're setting the values in state in your onChange, but then never using those values in your inputs - you get defaultValue from props, but never assign value={this.state.profile.firstName} etc.
The error you're seeing points to props.firstName or props.lastName in profileActions.js being null/undefined (trying to access the 0th index on null/undefined will throw a TypeError). Are you setting initial values for those anywhere?
I'd suggest getting value for each of your inputs from state, and make sure you have initial data for first and last names.