Facing issue with React-hook forms - react-native

I copied/paste the first example of the React Hook Forms from NB 3.0 and getting this error. TypeError: errors is not an Object. (evaluating '"firstName" in errors'). Any idea why?

The example provided here Native Base V3 React-Hook_forms does not use the controller correctly to get onChangeText state and to catch errors for the value, to fix this change the following;
Change the line: const { control, handleSubmit, errors } = useForm(); to const { control, handleSubmit, watch, formState: { errors } } = useForm();
In the Controller change render={({ onChange, onBlur, value }) to render={({ field: { onChange, onBlur, value } })
In the Input component change onChangeText={(val) => onChange(val)} to onChangeText={onChange}
Reference is from the integration example on the React-Hook-Form website here: React Hook Form with React Native

Related

React Native app with react-hook-form not working (View config getter callback form component 'input' must be a function (received 'undefined')

I'm creating a mobile app with React Native and I need to use a form. I want to use react-hook-form, but I can't get it to work, even in a newly created project. I did the following:
Created new React Native projects: it runs as it should
npm install react-hook-form
copy-paste following code to App.js:
import React from "react";
import { useForm } from "react-hook-form";
export default function App() {
const { register, handleSubmit, watch, formState: { errors } } = useForm();
const onSubmit = data => console.log(data);
console.log(watch("example")); // watch input value by passing the name of it
return (
/* "handleSubmit" will validate your inputs before invoking "onSubmit" */
<form onSubmit={handleSubmit(onSubmit)}>
{/* register your input into the hook by invoking the "register" function */}
<input defaultValue="test" {...register("example")} />
{/* include validation with required or other standard HTML validation rules */}
<input {...register("exampleRequired", { required: true })} />
{/* errors will return when field validation fails */}
{errors.exampleRequired && <span>This field is required</span>}
<input type="submit" />
</form>
);
}
It gives following error: screenshot of emulator
I have no idea what's the problem. Is there something wrong with the installation of react-hook-form as it doesn't recognize the input field?
Thanks!

React-native Formik setFieldValue

Here is a simplified version of my code.
Notice the setFieldValue_ and this.setFieldValue_ = setFieldValue;
This code works fine, I'm able to get the output when submit button is clicked.
I'm actually wondering if this is the right way to do it? If not, can you point me to the right direction? Also what is this method called? (assigning class variable to some function and use it within another function)
class MyComponent extends React.Component {
setFieldValue_;
someFunction() {
this.setFieldValue_("name", value);
}
render() {
return (
<Formik
initialValues={{
something: ""
}}
onSubmit={values => console.log(values)}
>
{({
setFieldValue,
}) => {
this.setFieldValue_ = setFieldValue;
<ThirdPartyCustomComponent onChange={this.someFunction} />
}}
</Formik>
}
}
I would personally have the onChange simply call formik set field value there and then rather than using different functions. Strictly speaking you don't want to set the value like that because every re-render is setting the value again.
I would also recommend looking at custom formik inputs using the useField hook - https://jaredpalmer.com/formik/docs/api/useField. This will allow you to write a small wrapper around your third party component and formik. Noticing you have used a class based component you may want to do some short reading into react hooks before throwing yourself into using useField.
Docs example:
const MyTextField = ({ label, ...props }) => {
const [field, meta, helpers] = useField(props);
return (
<>
<label>
{label}
<input {...field} {...props} />
</label>
{meta.touched && meta.error ? (
<div className='error'>{meta.error}</div>
) : null}
</>
);
};

How to initiate props when rendering Component?

I have a Login Component where I want the user to choose Service from a Service Catalogue. The Picker gets and sets values to redux:
<Picker
selectedValue={this.props.service.id}
onValueChange={itemValue => this.props.setServiceType(itemValue)}>
{service_catalogue.map(service =>
<Picker.Item key={service.id} label={service.id} value={service.id} />
)}
</Picker>
But I don't know how to properly set the initial value. I set the default value in componentDidMount (the first item in the Catalogue), but I think componentDidMount is trigged on update? Is there a lifecycle function that is only triggered on rendering Component in React Native?
componentDidMount() {
this.props.setServiceType(service_catalogue[0].id)
}
So the problem that I'm facing is that even though the user might choose "Instructor" the service becomes service_catalogue[0] = "Cleaner". And if I don't setServiceType on componentDidMount no Picker appears, as this.props.service.id doesn't exist.
You can set default value for the props on the following way:
...
YourComponent.propTypes = {
myState: PropTypes.string,
}
YourComponent.defaultProps = {
myState: 'default value',
};
const mapStateToProps = state = ({
myState: state.myState,
});
export default connect(mapStateToProps)(YourComponent);
More info: https://reactjs.org/docs/typechecking-with-proptypes.html#default-prop-values

React Native Search Bar onCancel method doesn't fire

react-native: 0.53.0
react-native-elements: 1.0.0-beta4,
When I use Search Bar component from React Native Elements library, I am unable to capture 'onCancel' property. Code is provided below.
<SearchBar
lightTheme
clearIcon
platform={Platform.OS === "ios" ? "ios" : "android"}
placeholder="Search..."
returnKeyType='search'
cancelButtonTitle="Cancel"
onCancel ={()=>{this.doSomething();}}
onSubmitEditing ={()=>{this.handleSearch();}}
/>
I've wrote simple script with snack and tested. it works.
https://snack.expo.io/r12AYAoiG
Please change platform to ios and test it on iOS emulator.
I hope it give you some hints.
To conclude this, it was a syntax error. =(
when I made the call
onCancel={()=>{this.doSomething();}}
I wrapped it with the '{ }'. It should of been
onCancel={()=>this.viewHeader()}
I did want to point out though however that the calls :
onFocus ={()=>{this.hideHeader();}}
onBlur ={()=>{this.viewHeader();}}
are valid calls and it behaves properly. I think this is due to implementation by React-Native-Elements. The functions, onFocus() and onBlur() are explicitly written in the docs.
onFocus = () => {
this.props.onFocus();
UIManager.configureNextLayoutAnimation &&
LayoutAnimation.easeInEaseOut();
this.setState({ hasFocus: true });
};
onBlur = () => {
this.props.onBlur();
UIManager.configureNextLayoutAnimation &&
LayoutAnimation.easeInEaseOut();
this.setState({ hasFocus: false });
};
onChangeText = text => {
this.props.onChangeText(text);
this.setState({ isEmpty: text === '' });
};

React Native + Redux Form - Use keyboard next button to go to next TextInput field

I'm using Redux Form (RF) in a React Native application. Everything works fine but I can not figure out how to get the refs from the Field input to go to the next input field with Redux Form.
Without RF this solution would work just fine.
Here is my code:
class RenderInput extends Component {
const { input, nextField, refs,
meta: { touched, error, warning },
input: { onChange } } = this.props
render() {
return (
<Input
returnKeyType = {'next'}
onChangeText={onChange}
onBlur={input.onBlur}
onFocus={input.onFocus}
onSubmitEditing = {(event) => {
// refs is undefined
refs[nextField].focus()
}}/>
)
}
}
class Form extends Component {
render() {
return (
<Field
name="field1"
focus
withRef
ref='field1'
nextField = "field2"
component={RenderInput}/>
<Field
name="vendor"
withRef
ref="field2"
nextAction = "field3"
component={RenderInput}/>
)
}
}
I'm passing on the property nextField to the component to determine the next input field when the Next key on the keyboard is clicked but I can not get the refs property inside the RenderInput component.
Any idea how to get the refs property?
This solution passes props from the Form component to the RenderInput component and passes a function call back.
Here's the code:
class RenderInput extends Component {
const { input, refField, onEnter,
meta: { touched, error, warning },
input: { onChange } } = this.props
render() {
return (
<TextInput
ref = {refField}
returnKeyType = {'next'}
onChangeText={onChange}
onBlur={input.onBlur}
onFocus={input.onFocus}
onSubmitEditing={onEnter}/>
)
}
}
class Form extends Component {
render() {
return (
<Field
name="field1"
focus
withRef
ref={(componentRef) => this.field1 = componentRef}
refField="field1"
component={RenderInput}
onEnter={() => {
this.field2.getRenderedComponent().refs.field2.focus()
}}/>
<Field
name="field2"
withRef
ref={(componentRef) => this.field2 = componentRef}
refField="field2"
component={RenderInput}/>
)
}
}
So what happened here?
I assign the ref to local scope with ref={(componentRef) => this.field1 = componentRef} as #Ksyqo suggested. Thanks for the hint.
I pass refField="field1" to the RenderInput and assign the value to the input ref property ref = {refField}. This will add the input object to the refs property.
I assigned a onEnter function in the Field
I pass the function to the props of RenderInput and assign it to the onSubmitEditing={onEnter} function. Now we have bind the two functions together. That means if onSubmitEditing gets invoked the onEnter function gets invoked as well
Finally, refer to the local field field2, get the rendered Component and use the refs, which we assigned in the Input field, to set the focus. this.field2.getRenderedComponent().refs.field2.focus()
I don't know if this is the most elegant solution but it works.
For people who are using Redux Form + React Native Elements, just follow #Thomas Dittmar answer, and add the following prop to the 'FormInput' component: textInputRef={refField}
The newest version of React Native Element has added the focus() method, so you don't have to worry about that.
withRef is deprecated, use forwardRef instead.
I worked on getting a ref like this that worked for me.
const renderComp = ({
refName,
meta: { touched, error },
input,
...custom
}) => (
<MyComponent
ref={refName}
{...custom}
/>
)
<Field
name={name}
component={renderComp}
ref={node =>
isLeft ? (this.compRef1 = node) : (this.compRef2 = node)}
refName={node =>
(this.myRef= node) }
withRef
/>
now access instance functions like this.
this.myRef.anyFunc()
I had a slightly different use case, but I imagine it works for the above as well.
I used the focus action
import { focus } from 'redux-form';
dispatch(focus('signIn', 'email'));
Then in the (custom) form field that contains the TextInput, I added in the render function
<TextInput
ref="email"
/>
formStates.filter((state) => meta[state]).map((state) => {
if(state === 'active'){
this.refs.email.focus()
}
})
No worries about the component nesting/hierarchy anymore.