How to clear input value after submit with LabelInput - react-native

I create a component as below.
It allows the user to input their id and submits it.
Now I want to clear the input value after submit.
How to implement?
const InputUserModal = ({ onConfirm }) => {
const { register, control, handleSubmit, errors } = useForm();
useEffect(() => {
register({ name: 'userId' }, { required: true });
}, [register]);
return (
<View>
<Controller
control={control}
name="userId"
defaultValue=""
render={({ onChange, value }) => (
<LabelInput
label='user'
iconSetting={{
name: 'user',
type: 'feather',
}}
onSubmitEditing={handleSubmit(onConfirm)}
autoFocus
onChangeText={v => onChange(v)}
value={value}
/>
)}
/>
</View>
);
};

As you're using Formik, It provides reset function, which you can pass as a reference in onConfirm as below:
const InputUserModal = ({ onConfirm }) => {
const { register, control, handleSubmit, errors,resetForm } = useForm();
useEffect(() => {
register({ name: 'userId' }, { required: true });
}, [register]);
return (
<View>
<Controller
control={control}
name="userId"
defaultValue=""
render={({ onChange, value }) => (
<LabelInput
label='user'
iconSetting={{
name: 'user',
type: 'feather',
}}
onSubmitEditing={handleSubmit(onConfirm(values,resetForm)}
autoFocus
onChangeText={v => onChange(v)}
value={value}
/>
)}
/>
</View>
);
};
Assume that you render this component as below
const ParentComponent = ()=>{
const handleOnConfirm =(values,resetForm)=>{
// Your function to submit input values to a server
// then resetFormik Values
resetForm()
}
return (
<InputUserModal onConfirm={handleOnConfirm}/>
)
}

Related

React Native Validation with Formik - How can I replace the onchange of formik field with custom usestate hook?

I saw same question a couple of times but none of the answers made sense or solved it so maybe someone could help! I want to replace formiks onchange function with my own custom usestate hook. However, when I do that none of the validations work anymore, strangely none accept the error that field is required stays. Anyone know how to do it? Thanks!!
const DisplayingErrorMessagesSchema = Yup.object().shape({
password: Yup.string()
.min(2, 'Too Short!')
.max(50, 'Too Long!')
.required('Required'),
email: Yup
.string()
.email('Invalid email')
.required('Required')
.min(2, ({ min }) => `Password must be at least ${min} characters`)
});
const App = () => {
const { formData, handleInputChange } = useForm(
{
email: "",
password: ""
}
);
return (
<>
<Formik
initialValues={formData}
validationSchema={DisplayingErrorMessagesSchema}
onSubmit={values => console.log(values)}
>
{({ handleSubmit, isValid, values }) => (
<>
<Field
component={CustomInput}
name="title"
placeholder="Title"
/>
<Field
component={CustomInput}
name="post"
placeholder="Write post..."
multiline
numberOfLines={3}
/>
<Button
onPress={handleSubmit}
title="POST"
disabled={!isValid}
/>
</>
)}
</Formik>
</>
)
}
const CustomInput = (props) => {
const {
field: { name, onBlur, onChange, value },
form: { errors, touched, setFieldTouched },
...inputProps
} = props
const hasError = errors[name] && touched[name]
return (
<>
<TextInput
style={[
styles.textInput,
hasError && styles.errorInput
]}
value={value}
onChangeText={(text) => onChange(name)(text)}
onBlur={() => {
setFieldTouched(name)
onBlur(name)
}}
{...inputProps}
/>
{hasError && <Text style={styles.errorText}>{errors[name]}</Text>}
</>
)
}

react native how to focus on function component

I design a page to input account and password.
And I create a function component "LabelPwd" to password.
I want focus on password field after user submit account.
But nothing happened after submit account by the code below.
Can anyone provide some advise?
Main Page:
const [pwdFocused, setPwdFocused] = useState(false);
return (
<Controller
render={({ onChange, value }) => (
<LabelInput
error={errors ? errors.userId : errors}
label={t('common.userId')}
value={value}
autoFocus
onSubmitEditing={setPwdFocused(true)}
/>
)}
/>
<Controller
render={({ onChange, value }) => (
<LabelPwd
error={errors.password}
onChangeText={v => onChange(v)}
value={value}
setFocused={pwdFocused}
/>
)}
/>
);
LabelPwd
export default function LabelPwd({ value, onChangeText, error, setFocused }) {
const [pwdIcon, setPwdIcon] = useState('eye-off');
const pwdRef = useRef();
useEffect(() => {
//Seems didn't trigger here.
if (setFocused && pwdRef.current) {
pwdRef.current.focus();
}
}, [setFocused]);
function onPressPwdEye() {
if (pwdIcon === 'eye-off') {
setPwdIcon('eye');
setSecureMode(false);
} else {
setPwdIcon('eye-off');
setSecureMode(true);
}
}
return (
<>
<Input
errorMessage={error ? t('common.isRequired') : null}
label={t('common.password')}
rightIcon={{ type: 'feather', name: pwdIcon, size: 24, color: 'gray', onPress: onPressPwdEye }}
secureTextEntry={secureMode}
value={value}
onChangeText={onChangeText}
ref={pwdRef}
/>
</>
);
}

Hit undefined is not an object (this.state.text) when creating searchable flatlist

I am trying to create a search bar to filter data for flatlist. In the code below, I have created a list of name and pass the name list into flatlist. Then, I would like to pass in the input from search bar to
searchFilterFunction to filter the data. The issue is when I enter the page, I have encountered error "Undefined is not an object (evaluating this.state.text). Would like to know the cause and solution for this case.
const DATA = [
{
name: 'Name 1',
}, {
name: 'Name 2',
}, {
name: 'Name 3',
}, {
name: 'Name 4',
}, {
name: 'Name 5',
},
];
export default class NameListView extends React.Component<any, any> {
constructor(props) {
super(props);
this.state = {
loading: false,
text: '',
};
this.searchFilterFunction = this.searchFilterFunction.bind(this);
}
searchFilterFunction (text) {
const newData = DATA.filter(function(item) {
const itemData = `${item.name}`;
const textData = text;
return itemData.indexOf(textData) > -1;
});
this.setState({
text: newData
});
};
renderSeparator(){
return <View style={styles.separator}/>
}
renderHeader() {
return (
<SearchBar
placeholder="Choose Recipient"
lightTheme
round
onChangeText={text => this.searchFilterFunction(text)}
autoCorrect={false}
value={this.state.text}
/>
);
};
render() {
return (
<SafeAreaView>
<View>
<FlatList style={styles.flatList}
data={DATA}
renderItem={({ item }) =>
<ListItem
title={item.name}
chevron={{color : 'black'}}
leftIcon={<FontAwesome name={'user-circle'} size={25} color=
{'#E3E3E3'}/>}
/>
}
keyExtractor={item => item.name}
ItemSeparatorComponent={this.renderSeparator}
ListHeaderComponent={this.renderHeader}
stickyHeaderIndices={[0]}
/>
</View>
</SafeAreaView>
)
}
}
Since you are accessing this inside renderHeader it needs to either be bound or called with the correct scope.
You can change the call to something like:
ListHeaderComponent={this.renderHeader.bind(this)}
Or something like:
ListHeaderComponent={() => this.renderHeader()}

How to refresh FlatList on callback of modal

I'm successfully generating a FlatList from Realm with no issues. However, when I close my modal screen after adding a new record, the data doesn't refresh automatically (however it does after a "Pull to Refresh"). Can someone help me understand what needs to be called in the "HOW_TO_REFRESH" placeholder?
FlatList Generation:
export default class Accounts extends Component {
static propTypes = {
items: PropTypes.arrayOf(PropTypes.shape({
accountid: PropTypes.string.isRequired,
label: PropTypes.string.isRequired,
balance: PropTypes.string.isRequired
})),
onDeleteItem: PropTypes.func,
onRefreshItems: PropTypes.func,
onSelectItem: PropTypes.func,
refreshing: PropTypes.bool
};
static defaultProps = {
onDeleteItem: (item) => {
realm.write(() => {
realm.delete(realm.objectForPrimaryKey('Account', item.accountid));
})
},
onRefreshItems: () => { console.log('Refresh accounts'); },
onSelectItem: (item) => { console.log('onSelectItem ', item); },
refreshing: false
}
constructor(props) {
super(props);
this.state = ({
activeRow: null
});
}
renderItem(info, activeRow) {
return (
<AccountListItem item={info.item} onPress={() => this.props.onSelectItem(info.item)} />
);
}
render() {
const listSettings = {
data: realm.objects('Account'),
extraData: this.state.activeRow,
keyExtractor: (item, index) => item.accountid,
onRefresh: this.props.onRefreshItems,
refreshing: this.props.refreshing,
renderItem: (info) => this.renderItem(info, this.state.activeRow)
};
return (
<Container style={styles.container}>
<Header>
<Left></Left>
<Body>
<Title>Accounts</Title>
</Body>
<Right>
<Button transparent
onPress={() => this.props.navigation.navigate('AddAccount', {name: 'Accounts', onGoBack: () => HOW_TO_REFRESH})} >
<Icon name="ios-add" />
</Button>
</Right>
</Header>
<Container>
<FlatList {...listSettings} />
</Container>
</Container>
);
}
}
Called in my modal to navigate back:
navigation.goBack();
navigation.state.params.onGoBack();
define your own method
goBack= () => {
//do code for refresh flatlist
}
mention it when you are navigating
this.props.navigation.navigate('AddAccount', {name: 'Accounts', onGoBack: () => this.goBack})

How to get state from the store and pass to a new component?

ok i am fairly new to React-native and redux so please keep it simple for me. i did some research and read over may of the redux docs but perhaps i am not looking for the correct information.
first i create a plan.
class PlanCreate extends Component {
onButtonPress() {
const {title, city, district} = this.props;
this.props.planCreate({title, city, district});
}
render () {
return (
<View>
<CardSection>
<Input
lable="Title"
placeholder="New Plan"
autoCorrect={false}
value={this.props.title}
onChangeText={value => this.props.planUpdate({prop: 'title', value})}
/>
</CardSection>
<CardSection>
<Input
lable="City"
placeholder="Oakland"
autoCorrect={true}
value={this.props.city}
onChangeText={value => this.props.planUpdate({prop: 'city', value})}
/>
</CardSection>
<CardSection>
<Input
lable="District"
placeholder="Chinatown"
autoCorrect={true}
value={this.props.district}
onChangeText={value => this.props.planUpdate({prop: 'district', value})}
/>
</CardSection>
<CardSection>
<Button onPress={this.onButtonPress.bind(this)}>
Create Plan
</Button>
</CardSection>
</View>
);
}
}
const styles = {
pickerTextStyle: {
fontSize: 18,
paddingLeft: 20
}
};
const mapStateToProps = (state) => {
const {title, city, district} = state.planForm;
return {title, city, district}
};
export default connect(mapStateToProps, {planUpdate, planCreate})(PlanCreate);
then send it off to my rails backend server
export const planCreate = ({ title, city, district}) => {
return (dispatch) => {
var user_id = 1;
axios.post('http://localhost:3000/plans', { params: { user_id: user_id, title: title, city: city, district: district}
}).then((response) => {
dispatch({ type: PLAN_CREATE, payload: response.data});
Actions.plan();
});
};
then i update my state with the new plan_id form the server.
export default (state = INITIAL_STATE, action) => {
switch (action.type) {
case PLAN_UPDATE:
return { ...state, [action.payload.prop]: action.payload.value};
case PLAN_CREATE:
return { ...state, plan_id: action.payload.id};
default:
return state;
}
};
After this i navigate to a new page, from there i need to grab that newly assigned plan_id out of the state and reference it in a new post request to my server from the new page.