After months without reactjs I forgot how to solve this situation. I have a incremental input for numbers:
HTML:
<input
type="number"
value={stockQuantity}
defaultValue="1"
onChange={() => bookQuantity(stockQuantity)}
/>
React
const [stockQuantity, setStockQuantity] = useState(1);
const bookQuantity = (e) => {
setStockQuantity({ ...stockQuantity, [e.target.name]: e.target.value });
};
I just get errors I don't find the solution and I didn't find any previous work were I handle it.
Any idea?
You should define stockQuantity as an object initially:
const [stockQuantity, setStockQuantity] = useState({books: 1});
Then you can just setState in onChange event or create a separate function as you have already made.
You don't have to set the value prop
<input
type="number"
name="books"
defaultValue="1"
onChange={(e) => setStockQuantity({...stockQuantity, [e.target.name]: e.target.value})}
/>
You need to pass the event to your onChange handler and also add name to your input:
<input
type="number"
name="stockQuantity" // will be passed in e.target.name
value={stockQuantity}
defaultValue="1"
onChange={bookQuantity} // the same as onChange={(e) => bookQuantity(e)}
/>
I have found a little linear solution:
const [stockQuantity, setStockQuantity] = useState(1); // just numbers
const bookQuantity = (e) => {
setStockQuantity({ ...stockQuantity, [e.target.name]:
e.target.value });
};
HTML:
<input
type="number"
name="stock"
value={stockQuantity.books}
defaultValue="1"
onChange={bookQuantity}
// if you want you can use a placeholder
/>
Related
Why can't I put a value in the input? The problem is: I need to put a 'name' in <Form.Item> to apply the rules. Without that, the rules will not be able to work, but if you remove the name="userName" from <Form.Item the value appears at the input.
How can i solve that?
<Form autoComplete="off" layout="vertical" onFinish={handleFinish}>
<Form.Item name="userName" rules={getTextRule('name')}>
<Input value={fields?.firstName} name="firstName" onChange={(e) => {
handleInputChange(e)
}} />
</Form.Item>
</Form.Item>
simple we can code like
const [text,setText] = useState('')
return(
<input type='text' value={text} onChange={e=>setText(e.target.value)}/>
)
If you use the form you can let Ant Form manage the state by removing the value & the onChange props on the <Input />.
Else if you manage the state by yourself make sure to get the value from the e.target.value.
ex:
const [fields, setFields] = useState({})
const handleOnChange = (e) => {
setFields((state) => {
...state,
[e.target.name]: e.target.value,
})
}
return (
<Input
name="firstName"
value={fields.firstName}
onChange={handleOnChange}
/>
)
I have this input tag of type number and right now, it takes both negative and positive value. I want the input field to only accept only positive natural numbers
I have tried
<input type="number" min="0">
and for some reason, it does not work as expected.
You can use min property:
<input type='number' min={1} step={1} />
This might works for you.
<input type="number" name="test_name" min="0" oninput="validity.valid||(value='');">
But if you are working with forms in react, I would recommend using Formik and Yup(validation).
Formik: https://formik.org/docs/tutorial
Yup : https://github.com/jquense/yup
You can use regex so don't need any library.
const [value, setValue] = useState(1)
const onChange = (e) => {
const reg = /^$|^[0-9]+$/;
const newValue = e.target.value;
if (reg.test(newValue)) {
setValue(newValue);
}
}
<input value={state} onChange={onChange} />
I found out this also works well.
handleChange=(e)=>{
this.setState({
value: e.target.value
})
<input type="number"
value={this.state.value}
onChange={e=> e.target.value > 0 && handleChange}
/>
this is the magic here:
e.target.value > 0
it will force the input not to take a negative value.
I am making an update form for user but I can't type in input tag when I added handleChange
Here is my code base:
const handleChange = (event) => {
const { name, value } = event.target;
// Update state
updatePlayersData((prevState) => ({
...prevState,
[name]: value,
}));
};
<input
value={title}
onChange={handleChange}
placeholder={title}
pattern="^[a-zA-Z0-9 ]+"
minLength="1"
maxLength="20"
/>
Because you're setting your inputs value to title variable everytime and not updating your title value.
<input
value={title} // you are not updating title value and using it on your value
onChange={handleChange}
placeholder={title}
pattern="^[a-zA-Z0-9 ]+"
minLength="1"
maxLength="20"
/>
as I understand it, you want to specify a default value. Try this one:
<input
defaultValue={title} // now it will change when you update input string
onChange={handleChange}
placeholder={title}
pattern="^[a-zA-Z0-9 ]+"
minLength="1"
maxLength="20"
/>
Kindly provide name="name_of_field" property to input element.
It will assign the input to the specified name_of_field and you can, later on, use it as input.name_of_field
In your code input doesn't have any name attribute. But in onChange method the state is being updated based on the name of the input. Hence, the changes are not getting reflected in the input.
So by adding name="title" attribute to the input and providing value={data.title} should work. Below I have added a snippet for the same
const { useState } = React;
const App = () => {
const [data, setData] = useState({});
const handleChange = (event) => {
const { name, value } = event.target;
setData((prevState) => ({
...prevState,
[name]: value,
}));
};
return <input
value={data.title}
onChange={handleChange}
placeholder={data.title}
pattern="^[a-zA-Z0-9 ]+"
minLength="1"
maxLength="20"
name="title"
/>
}
ReactDOM.render(<App />, document.getElementById("react"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>
<div id="react"></div>
Note: I have replaced updatePlayersData with setData for the example purpose. Also, in your code as per your requirement you can add any name for the input. But then make sure the same prop in the data to be passed as value to the input.
I am testing this component, which is simply changing its state depending on new input into the input field and setting the value of the input element to that state.
function Login () {
//Login Credentials
const [loginCredentials, setLoginCredentials] = useState({ name: '' })
const handleChange = ({target}) => {
setLoginCredentials(prev => ({ ...prev, [target.name]: target.value }));
}
return (
<div className="login-container">
<h1>Log In</h1>
<div className="login-label-input">
<label htmlFor="name">Account Name
<input
type="name"
id="name"
name="name"
placeholder="Enter Name"
onChange={handleChange}
value={loginCredentials.name}
aria-label="name"
/>
</label>
</div>
</div>
)
}
and for some reason this test does not show the value of input to be "testUser" in screen.debug() but only "t"....
test("log in with empty name input returns error message", () => {
render(<Login />)
const nameField = screen.getByLabelText(/account name/i);
userEvent.type(nameField, 'testUser');
screen.debug()
});
Shouldn't this work? Why doesn't it? excerpt from screen.debug():
<label
for="name"
>
Account Name
<input
aria-label="name"
id="name"
name="name"
placeholder="Enter Name"
type="name"
value="t"
/>
</label>
In the current version of #testing-library/user-event: ^14.2.0 and its corresponding official docs, there is an example where calling userEvent.type is awaited:
test('type into an input field', async () => {
render(<input defaultValue="Hello," />)
const input = screen.getByRole('textbox')
await userEvent.type(input, ' World!')
expect(input).toHaveValue('Hello, World!')
})
Callback in test() needs to be declared as async then, of course.
Link to this in the docs at time of writing: https://testing-library.com/docs/user-event/utility/#type
Nice to know maybe: Also works with uncontrolled components.
If you update jest to the latest version it will work. Currently, the latest jest is 26.6.3
This issue was discussed here: https://github.com/testing-library/user-event/issues/387
Your attribute "type" is invalid. The value "name" doesn't exist, try "text".
Here is a React class I'm working on:
import React from 'react';
export default class ExpenseForm extends React.Component {
state = {
title: ''
};
onTitleChange = (e) => {
const title = e.target.value;
this.setState(() => ({title}));
};
render() {
return (
<div>
<form>
<input
type='text'
placeholder='title'
value={this.state.title}
onChange={(e) => this.setState(() => ({title: e.target.value}))}
required autoFocus/>
<textarea placeholder='Add a note for your expense'/>
<input type='number' placeholder='amount' required/>
<input type='submit' value='Add Expense'/>
</form>
</div>
);
}
}
This throws an error Uncaught TypeError: Cannot read property 'value' of null when executing onChange.
But when I restructure inner js of onChange into a separate function onTitleChange and calling that function: onChange={this.onTitleChange}, it works perfectly. What could be the reason behind this behavior?
Here you assigned onchange event as onChange={(e) => this.setState(() => ({title: e.target.value}))}, here e.target.value will not work, because its inside the setState() scope.
On expanding your function, we will get
function(e){
this.setState(function(){
return {
title: e.target.value
}
})
}
Here there is no e in function inside setSate(), so e.target.value will be error;
Since you dont want to compare with previous value and only need to set the value to title, you can use like
onChange={(e) => this.setState({title: e.target.value})}
There is no need for an extra function inside setState
I would guess, that your parameter e is not known in the inner arrow function.
You could write it like this:
<input
type='text'
placeholder='title'
value={this.state.title}
onChange={e => this.setState({ title: e.target.value })}
required
autoFocus
/>
That is because of React is utilizing event pooling and setState is a function executed in asynchronous context, so you observe them as nulls in the asynchronous setState callback.
You need to either persist event using e.persist() or save the value of event to variable, as in your method.
You don't need to use arrow function inside setstate.
change
onChange={(e) => this.setState(() => ({title: e.target.value}))}
to:
onChange={(e) => this.setState({title: e.target.value})}