When I type something in my custom field it loses focus and needs to be clicked again in order to add data, Below is the sandbox link to code. It only happens when I pass error and touched props to check for validation, If I remove that it works perfectly.
https://codesandbox.io/s/formik-example-forked-w0bub?file=/index.js
Browser I'm using is Chrom for windows
The input inside the functional component is recreated every time when there is state changes.
Read this blog post to know more the behaviour of nested functional components
To avoid recreation problem, you can follow the Formik example to create other functional component and use it inside your component.
const MyInput = ({ field, form, ...props }) => {
return <input {...field} {...form} {...props} />;
};
...
<Field
id="email"
name="email"
placeholder="Email"
component={MyInput}
/>
Here is the codesandbox for demo.
Related
I am following a tutorial to create a multistep form with formik by creating a formik wrapper component . So far it works for normal field elements. But I have certain scenarios where I wish to use setFieldValue to set some values of custom component , the formik helpers are inaccessible to the child elements of the wrapper.
Can someone help me on how can I use formik helpers to set values of a child element of a wrapper.
Here is the example link which I am following.
This is what I am trying to achieve -
<FormikStepper
initialValues={{...values}}
onSubmit={someFunction}
onReset={() => {}}>
<FormikStep label='Step 1' validationSchema={Step1ValidationSchema}>
<label>Some Label</label>
<input
name='image'
type='file'
className=''
onChange={(e) => {setFieldValue("image", e.target.files[0]);}}
/>
<ErrorMessage name='image'/>
</FormikStep>
How can I be able to access it for setting the value of a child. I tried creating a context but I am confused on where to initialize the context .i.e As to where and how should I initialize the context for this particular scenario.
Better way is to extract input into separate component and then you can use setFieldValue inside that component:
const ImageInput = (props) = {
const [setFieldValue] = useFormikContext()
...
}
The reason why it works is that all your components wrapper by formik Form.
im currently trying to create an dynamic form that uses a sub component to render out some input fields as createing them static would exceed a limit. I pass the states for the the form i made aswell as some date and the change form. But when i render the form as it does so fine! as soon as i change the state its sends a warning about uncontrolled components that you can read about it here
I have tried pre-setting all the fields with empty defaults but it doesnt help.
Am i doing it somewhat correct or totally wrong? or what is the correct way, or what am i doing wrong. thanks in adbance.
As for the code looks like this:
Edit.js
export default function InventoryItemEdit() {
const [form, setForm] = useState({});
function handleFormChange(e) {
setForm({ ...form, [e.target.name]: e.target.value });
}
const variants = (
<ItemVariants
form={form}
onChange={handleFormChange}
fields={form.sizes}
/* ^^ fields data fetched from the server i set via use effect hook when loading the page */
/>
);
const updateItem = async (event) => {
event.preventDefault();
/* Do form submit post */
};
return (
<form onSubmit={updateItem}>
<div>
<p htmlFor="name">Name</p>
<input
id="name"
name="name"
onChange={handleFormChange}
value={form.name}
type="text"
required
placeholder="Name of Item"
/>
</div>
{variants}
</form>
);
}
As for the sub component ItemVariants it looke like this
ItemVariants.js
export default function ItemVariants({
form = {},
onChange = '',
fields = [],
}) {
return (
<>
{fields.map((row, index) => (
<div>
<span>
{row.name}
</span>
<input
type="text"
id={`variant${index}`}
name={`variant${index}`}
onChange={onChange}
value={form[`variant${index}`]}
required
min="0"
placeholder="0"
defaultValue="0"
/>
</div>
))}
</>
);
}
Controlled component: is when your input value is coming from a single source of truth a state(meaning for an input value to change, you need to update the state holding the value)
Uncontrolled component: is when your input value is not coming from a state but rather it's coming from something we call useRef/createRef which helps to reference to react syntactic DOMNODE thus giving us the ability to interact with input in a false-actual-DOM(as if we were query an actual DOM input-node in pure-JS). Meaning if your input value is not coming from a state, it must come from a ref(ref.current.value which is equivalent to document.querySelector(theInputLocator).value).
Answer to your bug: I see that everything is okay, but the only issue is that you didn't set the initial state with the name key. Thats an analysing issue because in your code you doing [e.target.name]:e.target.value and the way inputs works generally is that event is triggered but must recent value is emitted when the event happens next. it works like a++.
Do this:
const [form, setForm] = React.useState({ name: '' });
The general rule of thumb is that always describe your form input keys when your inputs are predefine and not dynamic(in this case your name input is predefined).
So After digging reading this post i have to thank! #juliomalves for solution with value={form[`variant${index}`] ?? ''} or value={form[`variant${index}`] || ''}
I also found out i was accidently adding defaultvalue aswell as value which cannot be set at the same time i found out. After i tested it removed the default value and set it correctly to be a string! it now works like a charm!
Also thanks to #Emmanuel Onah for the explaination it really helped me understand more about the react states!
Thanks again for everyone that helped
Good afternoon devs !!
I have a little problem, I'm using reactJS, and I'm using react-form-hook, in which I use an TextField from Material-UI. When I fill an input with name cep, it calls a function that sends the content from this to an api, which returns, content to fill the input there, The problem happens that when I try to set my inputs with the returned content. The Input label remains on the field, as in the case shown in the photo, in the last input. That came the answer.
the fields first with the setValues of the react-form-hook, but the error persisted after I tried to set this way document.querySelector ('# inputStreet'). value = street;
Finally the way I decided was to create in this inputs that receive update a useState for each
const [srua, setSrua] = useState ('');
const [sbairros, setSbairros] = useState ('');
const [scity, setScidade] = useState ('');
const [sUF, setSUF] = useState ('');
Only in this way was he able to solve the problem of the label not being on the content of the input, as already exemplified in the photo in the last input, I believe this is not the most correct way, so I would like a help on how to solve this in a more efficient. just like that
Repository link.
The problem with your TextField is that the InputLabel does not shrink. the label shrinks when the TextField is in focus or when the value of the TextField is not empty.
But since you are setting the value programmatically, the input is not focused, the value is also not registered because it's uncontrolled which means the TextField keeps track and updates the value internally for you and ignore external value if provided.
In order to make the TextField controllable, as suggested from the name, you must take control of the TextField's value from the beginning which is what you did in the question.
You can also simplify this process by using react-hook-form's Controller. It's a wrapper component to help you pass common props to the controlled components
<Controller
render={({ onChange, onBlur, value, name }) => (
<TextField
onBlur={onBlur}
onChange={(e) => onChange(e.target.value)}
value={value}
name={name}
label="Email"
/>
)}
name="email"
control={control}
// need to initialize value to register the TextField as controlled
// if we don't provide, the default value is undefined, which means uncontrolled
defaultValue=""
/>
Which can be shortened to this
<Controller
render={(props) => <TextField {...props} label="Email" />}
name="email"
control={control}
defaultValue=""
/>
Live Demo
I am trying to make one login form in react .but I am getting this error
React does not recognize the handleChange prop on a DOM element. If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercase handlechange instead.
input value is also not setting input field when I type in input field it is not updating the state why ?
here is my code
https://codesandbox.io/s/quirky-clarke-qbkjw
<form noValidate>
<TextBox
label="Username"
name="username"
type="text"
helperText="Assistive text"
handleChange={handleChange}
handleMouseDownPassword={handleMouseDownPassword}
value={userId}
/>
<TextBox
label="Password"
name="password"
type="password"
helperText="Assistive text"
value={password}
showPassword={showPassword}
handleChange={handleChange}
handleClickShowPassword={handleClickShowPassword}
handleMouseDownPassword={handleMouseDownPassword}
/>
<div className="button-group">
<button>LOGIN</button>
</div>
</form>
In the TextBox component you're passing all the props from the parent via {...props}. Considering that TextField itself doesn't have handleChange property, I assume it passes it down to the underlying input DOM element, which doesn't recognise that prop.
What you can do is to extract the props used inside TextBox and collect the rest using the rest argument, so you don't end up passing unnecessary props down:
export default function TextBox({handleChange, handleClickShowPassword, handleMouseDownPassword, value, ...props}) {
Another option is to remove {...props} from the TextField component and explicitly pass all the necessary props.
Updated Sandbox
React doesn't like uppercase letters in the prop names. Instead of passing "handleChange", pass "handlechange". You will get a similar error for "handleMouseDownPassword".
Regarding the input issue, I don't think you've provided enough context. But you have to have a handleChange method to update the state each time the field is changed.
I changed the handleChange() function, you were only setting the VALUE state, you need to set the state userId when you write on the first input, and the password when you write to the second input
At b.js add props name={stateName} so the handleChange() can know which input is controlling
Check Demo for more:
https://codesandbox.io/s/gracious-heisenberg-z4q4z
(other answeres explained why you are getting that error in console ...props)
I have an input field in React, where I set the global name for my application.
I have the handlers set in the parent component called App.js
....
state = {
name: 'app_x',
isProcessedData: false,
isUploadedFiles: false,
isProcessedDBScan: false
}
setNameHandler = (e) => {
this.setState({name: e.target.value});
}
...
in my child component, I refer to the state and the handler via props
export default function Home(props) {
console.log(props)
return (
<div>
<p>Welcome to our application</p>
<TextField
id="outlined-name"
label="Name"
className={"textfiled"}
value={props.name}
onChange={props.handleChange} //the textfield loses focus after each time the input is changed
margin="normal"
variant="outlined"
/>
</div>
)
}
after each keystroke, the text field, is not focused anymore, because the entire UI is rendered.
I tried using React.useState("app_x")
for testing purposes, which worked fine, as long it's inside the component, but I need to pass down the state of the application to other components.
Is there a way to solve this?
I thought about using refs, and then passing a ref down as a callback instead, but as far as the most use cases I have looked at it's mostly relevant inside the same component?