I have a list and edit button when user click edit button opening a new modal. I want to auto populate the selected username mail etc. Server side response is {this.test.name} i give him to input value to auto populate but when user click edit button ı can see the name but ı couldnt change the input how do ı do that ?
Code :
<div className = "form__group field">
<input type="input" className="form__field" placeholder="Name" name="name" id="name" value={this.test.name} />
<label htmlFor="name" className="form__label">Adı-Soyadı</label>
</div>
You cannot change that input value because you've set the value to this.test.name and did not defined an onChange handler. So what you should do is create a state for your input field and on componentDidMount, populate this state with data from server.
Then on your input field
this.state = {
val: ''
}
<input value={this.test.name} onChange={e => setState({val: e.target.value})}/>
Maybe there can be a syntax error, because I am used to work with hooks now, but that's pretty much the gist of it
Keep the name in the state:
this.state = {
name: '',
}
(setState when you have it, if you retrieve it only on mount)
Pass value={this.state.name} to the input.
Pass onChange={handleNameChange} to the input.
const handeNameChange = (e) => {
setState({ name: e.target.value });
}
If you are using hooks, you could do something like this:
import { useState } from "react"; // import useState
export default function App() {
const [name, setName] = useState(""); // useState hook
// handle change event
const handleChange = (e) => {
e.preventDefault(); // prevent the default action
setName(e.target.value); // set name to e.target.value (event)
};
// render
return (
<div>
<input value={name} type="text" onChange={handleChange}></input>
<p>{name}</p>
</div>
);
}
First, we import the useState() hook to be able to use it, then we use it to store the state for the name value, you can give it an initial value of an empty string (""). In the handleChange() function, we prevent the default action and set the state to e.target.value, this is the input value passed by the event (as (e)). Every time the input changes, the state will update and the page will re-render.
You could check out my sandbox here
Related
React Hook Forms detect that I change the value of text input when I type something (onChange). But can it also detect the change if I enter data to the input by value={value}?
const validator = register(name);
I need something like
onValueSet={(e) => {
validator.onChange(e);
}}
I mean if I just set data by value={value} I get an error that this input is required. I don't want this error, because data was set by value={value}.
Here is my input:
<StyledInput
name={name}
maxLength={100}
value={value}
onChange={(e) => {
validator.onChange(e);
}}
/>
and my validation schema:
const validationSchema = Yup.object().shape({
first_name: Yup.string()
.required("required"),
});
You have to use reset here and call it when you received your initial form data. I assume you're doing an api call and want to set the result to the form. You can do so with useEffect, watching when you're data has resolved and then reset the form with the actual values. This way you don't have to set the value via the value prop and let RHF manage the state of your inputs. You also don't need to set name prop, as RHF's register call returns this prop as well.
const Component = (props) => {
const { result } = useApiCall();
const { register, reset } = useForm();
useEffect(() => {
reset(result)
}, [result]);
return (
...
<StyledInput
{...register('first_name')}
maxLength={100}
/>
...
)
}
Here is a little CodeSandbox demonstrating your use case:
You can define an onfocus or onkeyup event and call the validation function there instead of onChange event.
<StyledInput
name={name}
maxLength={100}
value={value}
onfocus={(e) => {
validator.onChange(e);
}}
/>
Instead of triggering the validator when input changes, you can instead call your validator through the onBlur event. And I am not sure how you are using react-hook-form .. but the useForm hook has a config mode (onChange | onBlur | onSubmit | onTouched | all = 'onSubmit') on when to trigger the validation:
I have a form loaded with certain values in in its field. I'm unable to type in the value of fields or delete the existing default values when the form was rendered. Basically, I'm trying to add an Update operation in my form in which values are shown in field (e.g. On clicking an edit button, form is displayed with the values).
I tried to capture the event with onChange method but it's not working as I expected.
The default values are fetched as props from its parent and passed to the value argument of the form. I'm using semantic UI React components for the form.
Here is the example in codesandBox of what I'm trying to implement:
codesandbox
In the above example, variable is passed to value in form.
if you look at the error, it clearly says: A component is changing an uncontrolled input of type text to be controlled. Which means you have to store the values of name, email in state on initialization, and have those values changed on onChange event. And not update values only on onChange.
import React, { Component } from "react";
import { Form } from "semantic-ui-react";
class FormExampleClearOnSubmit extends Component {
state = {
name: "james",
email: ""
};
handleChange = (e, { name, value }) => this.setState({ [name]: value });
handleSubmit = () => this.setState({ email: "", name: "" });
render() {
const { name, email } = this.state;
return (
<Form onSubmit={this.handleSubmit}>
<Form.Group>
<Form.Input
placeholder="Name"
name="name"
value={name}
onChange={this.handleChange}
/>
<Form.Input
placeholder="Email"
name="email"
value={email}
onChange={this.handleChange}
/>
<Form.Button content="Submit" />
</Form.Group>
</Form>
);
}
}
export default FormExampleClearOnSubmit;
I have a React Bootstrap Form component
https://react-bootstrap.github.io/components/forms/#forms
I just need to be able to get the name/ref of the input box that the user is typing inside so I can update the state dynamically. I did this already with the standard Form using:
this.setState({
[event.target.name]: event.target.value
})
but I wanted to use React's Bootstrap form. I can already get the value of the Form input, but I can't find a way to get its reference name (like if the input box is for dealerName, I am unable to get the string 'dealerName' so I can update it dynamically instead of having to hardcode the state property name to a value to update it) so I can dynamically update the state. Without that, I would have to create multiple separate functions for all the different forms I have.
This is my sample React Bootstrap Form:
<Form>
<Form.Group controlId="formDealersAdd">
<Form.Label>userId:</Form.Label>
<Form.Control type="text" placeholder="userId" ref={this.userId} onChange={this.handleInputChange}/>
<Form.Label>dealerName:</Form.Label>
<Form.Control type="text" placeholder="dealerName" ref={this.dealerName} onChange={this.handleInputChange} />
<Form.Label>dealer id:</Form.Label>
<Form.Control type="text" placeholder={did} ref={this.did} onChange={this.handleInputChange} />
<Button variant="secondary" size="lg" onClick={this.handleDealersAddFormClick}>SUBMIT</Button>{' '}
</Form.Group>
</Form>
My constructor looks like this:
class App extends Component {
constructor(props) {
super(props);
this.userId= React.createRef();
this.dealerName = React.createRef();
this.did = React.createRef();
this.state = {
userId: '',
dealerName: '',
did: '',
};
}
}
And my handleInputChange function:
handleInputChange = (event) => {
event.preventDefault()
// manually hardcoding it like this causes issues and makes my code bad
this.setState({
userId: this.userId.current.value,
dealerName: this.dealerName.current.value,
did: this.did.current.value
})
}
I was originally handling the inputChange by simply setting the state with
this.setState({
[event.target.name]: event.target.value
})
and this worked fine for the standard Form (non-React Boostrap form) and it does return the correct value for the input that is being actively updated/being typed inside by a user, but event.target.name does not work.
Thus, as you can see above, I just manually hardcoded the values to be updated inside the state object, but this is messy and causes error when the user clicks to see a new Form on my website and the properties are null and the state tries to update so it crashes.
Is there a way to update my state properties for the inputs of the React Bootstrap form similar to how I used [event.target.name] : event.target.value for the regular Form?
To get its reference name, add values to the props name would be fine
Before:
<Form.Control type="text" placeholder="userId" ref={this.userId} onChange={this.handleInputChange}/>
After:
<Form.Control type="text" name="userId" placeholder="userId" ref={this.userId} onChange={this.handleInputChange}/>
Part of the project is as follows:
...
const INITIAL_STATE = {
email: '',
password: '',
error: null
}
const SignInPage = () => {
return(
<div>
<h2>Sign In</h2>
<SignInForm/>
<SignUpLink/>
</div>
)
}
const SignInFormBase = props => {
const[init,setInit] = useState(INITIAL_STATE);
const onSubmit = () => {
}
const onChange = (event) => {
setInit({
[event.target.name]: event.target.value
})
}
const isInvalid = init.password === '' || init.email === '';
return(
<form onSubmit={onSubmit}>
<input
name='email'
value={init.email}
onChange={onChange}
type='text'
placeholder='Email Address'
/>
<input
...
/>
<button disabled={isInvalid} type='submit'>Sign In</button>
{init.error && <p>{init.error.message}</p>}
</form>
)
}
const SignInForm = compose(
withRouter,
withFirebase
)(SignInFormBase)
export default SignInPage;
export {SignInForm}
The problem is:
When I replace the values in init with setInit in the onChange function, I get the following error.
Warning: A component is changing a controlled input of type text to be uncontrolled. Input elements should not switch from controlled to uncontrolled (or vice versa) . Decide between using a controlled or uncontrolled input element for the lifetime of the component.
Note: I have the same problem in the password section
You strip part of the code but I assume that you didn't read react hooks documentation good enough. By using hooks you won't get replacement for the setState which was previously merging the values. Therefore when you call
setInit({
[event.target.name]: event.target.value
})
you will replace whole init variable with the new object therefore other field will be pointing to undefined value and react will change component to uncontrolled, then again to controlled when you enter value. If you want to maintain object in state you need to do merging by yourself. Easiest way would be to use object spread as
setInit({
...init, // <- spread old state
[event.target.name]: event.target.value
})
With this code old state will remain between inputs. I would also suggest you to not infer state property from the field name as later you can easily introduce bug you can create curried global onChange as
const onChange = (field) => (event) => {
setInit({
...init,
[field]: event.target.value
})
}
return (
<input onChange={onChange('name')} />
)
Given the source code for a simple login form, see below. You see I want to use the username text field's value when I click the form's submit button. Since I need a reference to the actual DOM node to retrieve the value, I'm setting the usernameElement variable to that node.
const Login = ({ onLogin }) => {
let usernameElement
const handleSubmit = event => {
event.preventDefault()
onLogin(usernameElement.value)
}
return <form onSubmit={handleSubmit}>
<input
type="text"
name="username"
ref={node => { usernameElement = node }}
/>
<button type="submit">Login</button>
</form>
}
So, how would I make an functional approach to that problem, or simply get rid of the let variable?
Apparently, the correct approach to this is to make use of the component's state, meaning you need a stateful component instead of the stateless one.
// untested
class Login extends Component {
state = { username: '' }
handleChange = event => {
this.setState({ username: event.target.value })
}
handleSubmit = event => {
event.preventDefault()
this.props.onLogin(this.state.username)
}
render = () =>
<form onSubmit={this.handleSubmit}>
<input
type="text"
name="username"
value={this.state.username}
onChange={this.handleChange}
/>
<button type="submit">Login</button>
</form>
}
Using this, the username is always bound to this.state.username. The handleSubmit method can just use the username from the component's state.
See this page for further information: https://facebook.github.io/react/docs/forms.html