React component is changing an uncontrolled input to be controlled error - javascript

please , how can i get over this error of component is changing an uncontrolled input to be controlled. This is likely caused by the value changing from undefined to a defined value, which should not happen. Decide between using a controlled or uncontrolled input element for the lifetime of the component.
this prevent the input field from showing what i am typing.
const [sellerName, setSellerName] = useState();
const [storeName, setStoreName] = useState("");
...
<form className="registerInputContainer customerEditInput">
<div className="regInput passForm ">
<span className="userEmail">Owner's Full name (Required)</span>
<div className="passwordContainer editCusInputField">
<input
placeholder="your name"
value={sellerName }
onChange={(e) => setSellerName(e.target.value)}
className="passwordInput regInputField"
/>
</div>
</div>
<div className="regInput passForm ">
<span className="userEmail">Store Name (required)</span>
<div className="passwordContainer editCusInputField">
<input
placeholder=""
required
value={storeName || ""}
onChange={(e) => setStoreName(e.target.value)}
className="passwordInput regInputField"
/>
</div>
</div>
...
</form>
i have tried some of the solution i saw on stackoverflow but they are not working . thanks you all

Related

React: TypeError: null is not an object (evaluating 'event.target.id')

I'm trying to save form input into the state object.
const [newMovie, setNewMovie] = useState({
name: "",
ratings: "",
duration: "",
});
const handleChangeEvent = (event) => {
console.log(event.target.value);
setNewMovie((prevState) => {
return { ...prevState, [event.target.id]: event.target.value };
});
console.log(newMovie);
};
This is called for this form:
<form onSubmit={handleFormSubmit}>
<div className="layout-column mb-15">
<label htmlFor="name" className="mb-3">
Movie Name
</label>
<input
type="text"
id="name"
placeholder="Enter Movie Name"
data-testid="nameInput"
value={newMovie.name}
onChange={handleChangeEvent}
/>
</div>
<div className="layout-column mb-15">
<label htmlFor="ratings" className="mb-3">
Ratings
</label>
<input
type="number"
id="ratings"
placeholder="Enter Rating on a scale of 1 to 100"
data-testid="ratingsInput"
value={newMovie.ratings}
onChange={handleChangeEvent}
/>
</div>
<div className="layout-column mb-30">
<label htmlFor="duration" className="mb-3">
Duration
</label>
<input
type="text"
id="duration"
placeholder="Enter duration in hours or minutes"
data-testid="durationInput"
value={newMovie.duration}
onChange={handleChangeEvent}
/>
</div>
</form>
Issue is as soon as I start typing, right after the first word, React throws the error: "TypeError: null is not an object (evaluating 'event.target.id')" and a couple warnings pop up:
The exact error is as follows. I'm not sure why this is happening because the id parameter is clearly defined in the form. Can anyone help me fix this problem?
Update 1
Logging the entire event.target shows that "id" parameter is present (as per my understanding):
Update 2
Tried extracting the keys and value prior to calling the set state function but now I'm unable to enter anything in the input fields. Please note: It says that "myKey" is not used anywhere despite the fact that I'm literally using it inside the update state function.
Browser logs:

redux-form How to have initial value in the input field

I use redux-form for my form, following the example: https://redux-form.com/8.3.0/docs/api/fields.md/
So the <Fields /> is like so:
<Fields
names={['firstName', 'lastName']}
component={input}
validate={{
firstName: (value, allValues, props, name) => 'error'
}}
warn={{
lastName: (value, allValues, props) => 'warning'
}}
/>
the fields component that i render is this
const renderFields = (fields) => (
<div>
<div className="input-row">
<input {...fields.firstName.input} type="text"/>
{fields.firstName.meta.touched && fields.firstName.meta.error &&
<span className="error">{fields.firstName.meta.error}</span>}
</div>
<div className="input-row">
<input {...fields.lastName.input} type="text"/>
{fields.lastName.meta.touched && fields.lastName.meta.error &&
<span className="error">{fields.lastName.meta.error}</span>}
</div>
</div>
)
So far so good, the form displays the 2 input fields and i can add values into them.
But how do i pass default values into the input's ?
When i add the value property into the input, i cant edit the input afterwards.
For example, i add the value prop with a value like so:
const renderFields = (fields) => (
<div>
<div className="input-row">
// add value="my name"
<input {...fields.firstName.input} type="text" value="my name" />
{fields.firstName.meta.touched && fields.firstName.meta.error &&
<span className="error">{fields.firstName.meta.error}</span>}
</div>
<div className="input-row">
// add value="my last name"
<input {...fields.lastName.input} type="text" value="my last name" />
{fields.lastName.meta.touched && fields.lastName.meta.error &&
<span className="error">{fields.lastName.meta.error}</span>}
</div>
</div>
)
In that way, the inputs have always the same init value.
Any help on how to have default value and also be able to edit it, thank you.
When you provide the value prop you will need to provide onChange function as well and handle the state - https://reactjs.org/docs/forms.html#controlled-components
and from redux-form docs: https://redux-form.com/8.3.0/docs/api/field.md/#-code-onchange-event-newvalue-previousvalue-name-gt-void-code-optional-
You need a state variable to hold the input value.
const [inputValue, setInputValue] = useState('');
In the input tag, use the previously declared state variable as value & in onChange of input, set the input value to the target value.
<input type="text" value={inputValue} onChange={e => setInputValue(e.target.value)} />
You can use prop defaultValue, as mentioned in Redux Form documentation :https://redux-form.com/6.0.0-alpha.4/docs/api/field.md/#props
<Field component={your custom component} defaultValue={}/>

React, cannot reset checkbox to default unchecked state

I'm trying reproduce Youtuber Traversy Media's React JS crash course 2021 Task Tracker project with Reactstrap, and using the same method (a component level hook) to create a form with a checkbox in it, and I set up a method, make sure after the form submitted, the text area will be set to empty and the checkbox set to false, and therefore unchecked. When I hit submit, the checkbox had set to false, but remain checked.
From the React dev tool, the value is reset to false and the checkbox should be unchecked, I don't know what went wrong, I did the exact same thing as the video did. I have problem pasting code here, so left out non-related part, like the input text code. Thanks in advance!
const [reminder, setReminder] = useState(false);
const onSubmit = (e) => {
e.preventDefault()
if (!text) {
alert('Please add a task')
return
}
onAdd({ text, day, reminder })
setText('')
setDay('')
setReminder(false)}
{/* checkbox here */}
<div className="mb-3 form-check">
<input
type="checkbox"
id="checkbox1"
className="form-check-input"
value={reminder}
onChange={(e) => setReminder(e.currentTarget.checked)}
/>
<label className="form-check-label" htmlFor="checkbox1">
Set reminder
</label>
</div>
{/* submit button */}
<div className="d-grid">
<button type="submit" className="btn btn-primary">
Submit
</button>
</div>
Doing as below would work. Notice I'm using checked and not value as you did, the reason why it's not working for you.
const [reminder, setReminder] = useState(false);
<input
type="checkbox"
id="checkbox1"
className="form-check-input"
checked={reminder}
onChange={(e) => setReminder(e.currentTarget.checked)}
/>
To know more about the difference between value and checked, you can visite this link from MDN.

vee-validate#4.x - how to manually validate field

While using
vee-validate#4.4.5
vue#3.1.4
I encountered following problem:
<Form #submit="onSubmit" :validation-schema="schema">
<div class="mb-3">
<label for="edit-email" class="form-label">E-mail</label>
<Field
id="edit-email"
class="form-control"
name="email"
type="text"
:validateOnInput="true"
/>
<ErrorMessage class="invalid-feedback" name="email" />
</div>
<button #click="checkEmail" type="button">Check e-mail address</button>
<!-- non-important part of the form -->
</Form>
I'd like to manually validate <Field /> when the button is clicked (error message should appear) and then I want to use the field's value to perform another action.
I wrote following code:
import { useFieldValue } from 'vee-validate';
// setup
setup() {
const schema = object({
email: string().required().email().label("e-mail"),
});
function verifyEmail(v) {
const emailValue = useFieldValue("email");
console.log(emailValue); // empty ComputedRefImpl
}
return {
schema,
verifyEmail,
};
},
}
And this doesn't work.
emailValue is returned as ComputedRefImpl with an undefined value.
I guess I'm mixing Components & Composition API flavors of vee-validate. But still don't know how to resolve this issue.
Created sandbox with this: https://codesandbox.io/s/vue3-vee-validate-form-field-forked-xqtdg?file=/src/App.vue
Any help will be much appreciated!
According to vee-validate's author:
https://github.com/logaretm/vee-validate/issues/3371#issuecomment-872969383
the useFieldValue only works as a child of a useForm or useField.
So it doesn't work when <Field /> component is used.

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.
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.
Your form inputs values should be targetting userData instead of user i.e
<input
...name="name"
value={userData.name} />
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.

Categories

Resources