Hello World!
I want to render data into my contact form screen (I want the screen to be 100% configurable using call api)
Fisrt I want to render the title[Contact Us] and the subtitle[Enter your details to contact us] from the configuration Array -->Done
Second I want to render the objects on the Form Array into an inputs -->Not Yet
this is the Code:
import React, { useState,useEffect } from 'react';
import {
View,
Text,
TextInput,
SafeAreaView,
Keyboard,
ScrollView,
Alert,
} from 'react-native';
import COLORS from '../src/conts/colors';
import Button from '../src/views/components/Button';
import Input from '../src/views/components/Input';
import Loader from '../src/views/components/Loader';
const ContactForm = ({navigation}) => {
const [inputs, setInputs] = React.useState({
firstname: '',
lastname: '',
email: '',
note: '',
});
const [errors, setErrors] = React.useState({});
const [loading, setLoading] = React.useState(false);
const validate = () => {
Keyboard.dismiss();
let isValid = true;
if (!inputs.firstname) {
handleError('Please input first name', 'firstname');
isValid = false;
}
if (!inputs.lastname) {
handleError('Please input last name', 'lastname');
isValid = false;
}
if (!inputs.email) {
handleError('Please input email', 'email');
isValid = false;
} else if (!inputs.email.match(/\S+#\S+\.\S+/)) {
handleError('Please input a valid email', 'email');
isValid = false;
}
if (!inputs.note) {
handleError('Please input note', 'note');
isValid = false;
}
if (isValid) {
submitData();
}
};
const submitData = ()=>{
fetch("https://flow.simpas.ai:2021/react/contact",{
method:"post",
headers:{
'Content-Type': 'application/json'
},
body: JSON.stringify({
firstname: inputs.firstname,
lastname: inputs.lastname,
email: inputs.email,
note: inputs.note,
})
})
.then(res=>res.json())
.then(data=>{
alert(`${data.firstname} is saved successfuly`);
navigation.navigate("Home")
})
.catch(err=>{
alert("someting went wrong")
})
};
const handleOnchange = (text, input) => {
setInputs(prevState => ({...prevState, [input]: text}));
};
const handleError = (error, input) => {
setErrors(prevState => ({...prevState, [input]: error}));
};
const [data, getData] = useState([])
const URL = "https://flow.simpas.ai:2021/react/contact";
useEffect(() => {
fetchData()
}, [])
const fetchData = () => {
fetch(URL)
.then((res) =>
res.json())
.then((response) => {
console.log(response);
getData(response);
})
}
return (
<SafeAreaView style={{ flex: 1}}>
<Loader visible={loading} />
<ScrollView
contentContainerStyle={{paddingTop: 50, paddingHorizontal: 20}}>
<Text style={{color: COLORS.black, fontSize: 40, fontWeight: 'bold',fontFamily: 'Roboto',textAlign: 'center'}}>
{data?.title}
</Text>
<Text style={{color: COLORS.grey, fontSize: 18, marginVertical: 10,fontFamily: 'Roboto',textAlign: 'center'}}>
{data?.subtitle}
</Text>
<View style={{marginVertical: 20}}>
<Input
onChangeText={text => handleOnchange(text, 'firstname')}
onFocus={() => handleError(null, 'firstname')}
iconName="account-outline"
label="First Name"
placeholder="Enter your first name"
/>
<Button title="Contact Us" onPress={validate} />
</View>
</ScrollView>
</SafeAreaView>
);
};
export default ContactForm;
This is The Json Data:
{
"title":"Contact us",
"subtitle":"Enter your details to contact us",
"action":"form",
"configuration":[
{
"title":"Contact us",
"subtitle":"Enter your details to contact us",
"type":"action",
"actiontype":"form",
"posturl":"https://flow.simpas.ai/interview/content/123456/businesscard/",
"form":[
{
"fieldtype":"field",
"title":"First Name",
"fieldname":"firstname",
"placeholder":"Enter your first name",
"iconurl":"https://www.creativefabrica.com/wp-content/uploads/2019/02/People-Icon-by-Kanggraphic-1-580x386.jpg",
"fieldvalue":"",
"required":true
},
{
"fieldtype":"field",
"title":"Last Name",
"fieldname":"latstname",
"placeholder":"Enter your last name",
"iconurl":"https://www.creativefabrica.com/wp-content/uploads/2019/02/People-Icon-by-Kanggraphic-1-580x386.jpg",
"fieldvalue":"",
"required":true
},
{
"fieldtype":"email",
"title":"Email",
"fieldname":"email",
"placeholder":"Enter your email",
"iconurl":"data:image/png;base64,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",
"fieldvalue":"",
"required":true
},
{
"fieldtype":"textarea",
"title":"Note",
"fieldname":"note",
"placeholder":"Enter your note",
"iconurl":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAOEAAADhCAMAAAAJbSJIAAAAclBMVEX///8AAAAODg6UlJQwMDA6Ojrw8PClpaX7+/vCwsIYGBiGhoZTU1P29vbU1NTn5+fc3Nytra1+fn4rKytdXV1OTk7IyMhlZWWfn58dHR2Pj49wcHCoqKjOzs4ICAhYWFi1tbUkJCR3d3dBQUE3NzdHR0dAC+4LAAAFpElEQVR4nO2d65aiOhBGRQXxiiKKl9bBsef9X/Esp0+ThCPBxKoKfda3f3Yvk+xlSEUIVYMBAAAAAAAAAAAAAAAAAADAz2a1yXfxWIp4l29WknqXcxSC815GL63GQfwejDcpv+D+M5jfg0/27zHM/NQ5s/pl4SaoYpvxCa5noe3+MlxzCWah1WqYvsUktJdGwmK4MDvZFvlpJMMpL7Zm5wsOwZHRRb5acnTSynKVG/2P6LswLsIzzyyxk5T6EOgvRX2OTslbf40p5zxda42zLdZBR6HNENFNfoOVGkZJ27IWKT5oW3bkQw2Edi3Y1O3uSNt1Z1ePZEParpqkF9J23bnwTNNlHXDHlM16UW/+t5QRWQXDA2GrfhxYQqKaGiEX0i/Uckp5waiFhrBRX1iWmkMvDSmvmHrXfSVs1Jfr92Aod9+14ZCwUV+GMPQBhqLA0AsYigJDL2AoCgy9gKEoMPQChqLA0AsYigJDL2AoSmDDZfIunU8jghpO4uPsXY7xxN5JSMNfEQ2/+mo4IRKMIuu3GNAwJjOM+2m4PJIZHm3LTcDvcPt8uB5sbd0ENPxNZvi7p4Z0hxetB0lCRouMZq2J7Q/ow+5pVtP36ToqgH2pFzAUBYZewFAUGHoBQ1Fg6AUMRYGhFzAUBYZewFCRvk9XF0ENp+U9fpd72fHyX0hD8zVPf/K+GlZEglFU9dTwTmZ476fh//+5RXojM7zZFtSAs7R8PlwPrK8WBjSkyyphva0fMlpchs8H7MjQ/tpd2D3NdPI+XW/7Y1/qBQxFgaEXMBQFhl7AUBQYegFDUWDoBQxFgaEXMBQlqOF6XizcyN0zFIY0VKmIHHDOCxzQcO8jGEUnx8EENPzjZxg55uj+gc8tHDOk/cDnFo6G9efkZ+ni6fi7cRxM/TmWbGZWw/XT8XfS8TJek8z3g1ZejBZeD4HnjmNRnVDm3Hs14ieHuSMj52S5KrM/ZRGBHu3atFePKDMJ98hQSytOmd2zP4baU9ghZSLh/hiqNMJRTFmvpDeG+lGBgrLhvhgaFVJcw4yVfhiuza19Rdl2HwyTeWRCmtI4pGG6XC6T9eQ/2QxmpIWRQhlm+3l5vz0/w0KbHD6MYWX9sUKbWTyAYXroOH5EW/1B3nDaWXiJtj9pw7S7NJj9HLEzwobJrVOQukaDrOEr9wqOxEX0RA3bBQtVt490yzaQNUxabkqWhyxRyyt1HR1Jw50pdswnm2p6+XvwW+3byGvBCBoapcGGJ/13vPbrl7zilJyhcZJ6bh7ZVyHkRt6vnKEeCBtflFbribZM0AMxQ20dvTYXE5WkaUbfsZih9uZUM6Sf1L8q+o7FDJVF86eDNket7wx5ImWoiuN9Nv6TaonEOArmShmqgNcMB4USJC4p94WU4e27n3Fj26mfEGCpLilkuKwtGttOvbQjfaR4IGSoVpN9y9+78mJ6I2SoDnMYsVD/sUH6sEJDyLCejFd9O2r8muIqgSpUs6s2nGnf1Fq/I+V69uZlhOqu1QXsbmrLbRxDYroIB2K18+pwqOpIbnTBO1+VZaH6h/Wd+z/ffzHe8J8xlo2XqWGpDlX9e5ovM99/ZxQUqkOq4vpXVG8cXuEttCxSS3ZhyGSFKchcH1SiHrC2ag6apdz5S2VL1HRWcW80qBqPZY78xdz563Jrk3I0Nv2iBV+YqGGvrW5LJE38FKYF/Wkl/eYwLVr1WG7LPMO4kVkSXxbTNrmoMzM0Iebilq/ILo1sY0tsw7bXfkLjqfq2yE+jt5mfreffY9Eq2cnVNhYW2CJTC3TZWV5jLhAjGqw7jw8QkoutMDpZMxSzceLfxLTQfUiCgLgKpfdgT1dr5Tn3E/cmu4u0YpyqxSG03hcXlrlaHi7yi2c7q02+i8cEfMa7Mv+YrojPxwAAAAAAAAAAAAAAAAAAAPSPfwBbfFMb/xNrvgAAAABJRU5ErkJggg==",
"fieldvalue":"",
"required":true
}
]
}
]
}
The output should look like this:
enter image description here
Check this approach
You should keep 2 different states for the form data and other stuff such as title, sub title, etc.
Related
I don't know why only on IOS emulator keyboard is not showing But on android it's working fine. I am trying to take user input for authentication and sending the data to the real-time database firebase.
import React, { useState, useReducer, useEffect, useCallback } from "react";
import {
KeyboardAvoidingView,
ScrollView,
View,
Button,
StyleSheet,
ActivityIndicator,
Alert,
} from "react-native";
import { useDispatch } from "react-redux";
import Input from "../../components/UI/Input";
import Card from "../../components/UI/Card";
import Colors from "../../constants/Colors";
import * as authActions from "../../store/actions/Auth";
const FORM_INPUT_UPDATE = "FORM_INPUT_UPDATE";
const formReducer = (state, action) => {
if (action.type === FORM_INPUT_UPDATE) {
const updatedValues = {
...state.inputValues,
[action.input]: action.value,
};
const updatedValidities = {
...state.inputValidities,
[action.input]: action.isValid,
};
let updatedIsFormValid = true;
for (const key in updatedIsFormValid) {
updatedIsFormValid = updatedIsFormValid && updatedValidities[key];
}
return {
formIsValid: updatedIsFormValid,
inputValidities: updatedValidities,
inputValues: updatedValues,
};
}
return state;
};
const AuthenticationScreen = (props) => {
const [Isloading, setIsloading] = useState(false);
const [error, setError] = useState();
const [IsSignup, setIsSignup] = useState(false);
const dispatch = useDispatch();
const [formState, dispatchFormState] = useReducer(formReducer, {
inputValues: {
email: "",
password: "",
},
inputValidities: {
email: false,
password: false,
},
formIsValid: false,
});
const authHandler = async () => {
let action;
if (IsSignup) {
action = authActions.signup(
formState.inputValues.email,
formState.inputValues.password
);
} else {
action = authActions.login(
formState.inputValues.email,
formState.inputValues.password
);
}
setError(null);
setIsloading(true);
try {
await dispatch(action);
props.navigation.navigate("Shop");
} catch (error) {
setError(error.message);
setIsloading(false);
}
};
useEffect(() => {
if (error) {
Alert.alert("An error occurred ", error, [{ text: "Okay" }]);
}
}, [error]);
const inputChangeHandler = useCallback(
(inputIdentifier, inputValues, inputValidities) => {
dispatchFormState({
type: FORM_INPUT_UPDATE,
value: inputValues,
isValid: inputValidities,
input: inputIdentifier,
});
},
[dispatchFormState]
);
return (
<KeyboardAvoidingView
behaviour="padding"
keyboardVerticalOffset={50}
style={styles.screen}
>
<Card style={styles.auth}>
<ScrollView>
<Input
id="email"
label="E-mail"
keyboardType="email-address"
required
email
autoCapitalize="none"
warningText="Please enter valid Email Address"
onInputChange={inputChangeHandler}
intialValue=""
/>
<Input
id="password"
label="Password"
keyboardType="default"
secureTextEntry
required
minLength={5}
autoCapitalize="none"
warningText="Please enter valid Password"
onInputChange={inputChangeHandler}
intialValue=""
/>
<View style={styles.buttonContainer}>
<View style={styles.button}>
{Isloading ? (
<ActivityIndicator size="large" color={Colors.primary} />
) : (
<Button
title={IsSignup ? "Sign up" : "Login"}
color={Colors.primary}
onPress={authHandler}
/>
)}
</View>
<View style={styles.button}>
<Button
title={`Switch to ${IsSignup ? "Login" : "Sign Up"}`}
color={Colors.secondary}
onPress={() => {
setIsSignup((prevState) => !prevState);
}}
/>
</View>
</View>
</ScrollView>
</Card>
</KeyboardAvoidingView>
);
};
AuthenticationScreen.navigationOptions = {
headerTitle: "Authenticate",
};
const styles = StyleSheet.create({
screen: {
flex: 1,
justifyContent: "center",
alignItems: "center",
},
auth: {
width: "80%",
maxWidth: 400,
maxWidth: 400,
padding: 20,
},
buttonContainer: {
marginTop: 20,
},
button: {
margin: 5,
},
});
export default AuthenticationScreen;
I can only be able to type email and password with my laptop keyboard and I have tried clicking on both fields to check whether the keyboard in the IOS emulator popup or not.
The keyboard is working fine on the android emulator.
The simulator detects that you have an external keyboard available and thus doesn't show the software keyboard. You can disable this behaviour using I/O -> Keyboard -> Connect Hardware Keyboard. Or you can Command + K to toggle the Software Keyboard manually.
I have react class component and I am trying to change it to function. But I don't know what to do with props.
This is my entire function.
const RegistrationForm = () => {
const [firstname, setFirstname] = useState('');
const [secondname, setSecondname] = useState('');
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [confirmDirty, setconfirmDirty] = useState(false);
const handleSubmit = e => {
e.preventDefault();
axioswal
.post('/api/users', {
firstname,
secondname,
email,
password,
})
.then((data) => {
if (data.status === 'ok') {
dispatch({ type: 'fetch' });
redirectTo('/');
}
});
};
const handleConfirmBlur = e => {
const { value } = e.target;
setState({ confirmDirty: state.confirmDirty || !!value });
};
const compareToFirstPassword = (rule, value, callback) => {
const { form } = props;
if (value && value !== form.getFieldValue('password')) {
callback('Two passwords that you enter is inconsistent!');
} else {
callback();
}
};
const validateToNextPassword = (rule, value, callback) => {
const { form } = props;
if (value && state.confirmDirty) {
form.validateFields(['confirm'], { force: true });
}
callback();
};
const { getFieldDecorator } = props.form;
const formItemLayout = {
labelCol: {
xs: { span: 24 },
sm: { span: 8 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 16 },
},
};
const tailFormItemLayout = {
wrapperCol: {
xs: {
span: 24,
offset: 0,
},
sm: {
span: 16,
offset: 8,
},
},
};
return (
<Form {...formItemLayout} onSubmit={handleSubmit}>
<Form.Item
label={
<span>
Firstname
<Tooltip title="What is your firstname?">
<Icon type="question-circle-o" />
</Tooltip>
</span>
}
>
{getFieldDecorator('Firstname', {
rules: [{ required: true, message: 'Please input your Firstname!', whitespace: true }],
})(<Input />)}
</Form.Item>
<Form.Item
label={
<span>
Secondname
<Tooltip title="What is your Secondname?">
<Icon type="question-circle-o" />
</Tooltip>
</span>
}
>
{getFieldDecorator('Secondname', {
rules: [{ required: true, message: 'Please input your Secondname!', whitespace: true }],
})(<Input />)}
</Form.Item>
<Form.Item label="E-mail">
{getFieldDecorator('email', {
rules: [
{
type: 'email',
message: 'The input is not valid E-mail!',
},
{
required: true,
message: 'Please input your E-mail!',
},
],
})(<Input />)}
</Form.Item>
<Form.Item label="Password" hasFeedback>
{getFieldDecorator('password', {
rules: [
{
required: true,
message: 'Please input your password!',
},
{
validator: validateToNextPassword,
},
],
})(<Input.Password />)}
</Form.Item>
<Form.Item label="Confirm Password" hasFeedback>
{getFieldDecorator('confirm', {
rules: [
{
required: true,
message: 'Please confirm your password!',
},
{
validator: compareToFirstPassword,
},
],
})(<Input.Password onBlur={handleConfirmBlur} />)}
</Form.Item>
<Form.Item {...tailFormItemLayout}>
{getFieldDecorator('agreement', {
valuePropName: 'checked',
})(
<Checkbox>
I have read the agreement
</Checkbox>,
)}
</Form.Item>
<Form.Item {...tailFormItemLayout}>
<Button type="primary" htmlType="submit">
Register
</Button>
</Form.Item>
</Form>
);
}
const WrappedRegistrationForm = Form.create({ name: 'register' })(RegistrationForm);
WrappedRegistrationForm.getInitialProps = async () => ({
namespacesRequired: ['common'],
})
export default withTranslation('common')(WrappedRegistrationForm);
For example in this line of code.
const { getFieldDecorator } = props.form;
I get this error.
ReferenceError: props is not defined
When I remove props then I get form is not defined. I know basic of props but cant figure out what to do in this case. I will be thankful for any help.
You're declaring a function component which receives its props as the first argument in the function.
const RegistrationForm = (props) => {
const [firstname, setFirstname] = useState('');
const [secondname, setSecondname] = useState('');
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [confirmDirty, setconfirmDirty] = useState(false);
All react functional components take props as a first argument
In other words, what you want is
const RegistrationForm = (props) => {
You have to pass props like this const RegistrationForm = (props) => {
I recommend this reading 5 Ways to Convert React Class Components to Functional Components w/ React Hooks
I have three functions:
Change Email
Change password
Change otherData
And One Button to call them ,
when the user changes his data without change Email Or Password I don't wont to call other function Change Email or Change Password just call the function Change other data, and when changing his email with other data like username, location I just want to call Change Email, change other data Function NOT Change Password
So how to handle this, and how to get a current password and save them in my state cuz when I wrote the wrong password, change Other Data function execute?
I'm using Firebase as a backend
Edit Screen
here is my code [React Native App]
import React, { Component } from 'react';
import firebase from "react-native-firebase";
import Icon from 'react-native-vector-icons/Ionicons';
import styles from "../Style/styles";
import AsyncStorage from '#react-native-community/async-storage';
import {
View,
Text,
KeyboardAvoidingView,
StyleSheet,
ActivityIndicator,
TouchableOpacity,
TextInput,
ScrollView
} from 'react-native';
class profileEdit extends Component {
constructor(props) {
super(props);
this.state = {
currentPassword: "",
newPassword: "",
currentUser: {
username: "",
email: "",
city: "",
mobileNumber: "",
},
data: {},
loading: true
}
}
async componentDidMount() {
try {
const userId = firebase.auth().currentUser.uid;
await this.setState({ userId });
console.log("#uid", this.state.userId);
let recentPostsRef = firebase.database().ref(`users/${userId}`);
await recentPostsRef.once('value').then(snapshot => {
this.setState({ currentUser: snapshot.val(), loading: false })
console.log(this.state.currentUser)
}).catch((error) => console.log("#error", error));
} catch (error) {
console.log("#CError", error);
}
}
reauthenticate = (currentPassword) => {
var user = firebase.auth().currentUser;
var cred = firebase.auth.EmailAuthProvider.credential(
user.email, currentPassword);
return user.reauthenticateWithCredential(cred);
}
_updateProfileData = async () => {
if (this.state.currentPassword === "") {
alert("please write your current password first!")
return;
} else {
await this._updateData();
await this.changeEmail();
await this.changePassword();
}
}
changePassword = () => {
if (this.state.currentPassword === "" || this.state.newPassword === "") {
return
} else {
this.reauthenticate(this.state.currentPassword).then(() => {
var user = firebase.auth().currentUser;
user.updatePassword(this.state.newPassword).then(() => {
console.log("Pssword updated!");
this._updateData();
this.setState({ newPassword: "", currentPassword: "" });
}).catch((error) => console.log(error.message));
}).catch((error) => console.log(error.message));
}
}
changeEmail = () => {
this.reauthenticate(this.state.currentPassword).then(() => {
var user = firebase.auth().currentUser;
user.updateEmail(this.state.currentUser.email).then(() => {
console.log("Email updated!");
this._updateData();
}).catch((error) => { console.log(error) });
}).catch((error) => { console.log(error) });
}
_updateData = () => {
const { userId, currentUser } = this.state;
let recentPostsRef = firebase.database().ref(`users/${userId}`);
recentPostsRef.update({
username: currentUser.username,
email: currentUser.email,
city: currentUser.city,
mobileNumber: currentUser.mobileNumber,
}).then(async () => {
let Data = await AsyncStorage.mergeItem('#MyProfile:data', JSON.stringify(currentUser))
console.log(Data)
alert("Great, your profile updated right now!")
}).then(async () => {
await AsyncStorage.getItem('#MyProfile:data')
.then(json => JSON.parse(json))
.then(currentUser => this.setState({ currentUser }))
.catch(error => console.log('#error' + error));
})
}
// _logout = () => {
// firebase.auth().signOut().then(() => {
// alert("Logout successfuly")
// setTimeout(() => {
// this.props.navigation.navigate("SignIn")
// }, 500)
// }).catch((error) => console.log("#error", error));
// }
render() {
const { currentUser, loading } = this.state;
if (loading) {
return (
<View style={{ justifyContent: "center", alignItems: "center", flex: 1 }}>
<Text>Just a moment.</Text>
<ActivityIndicator size="large" color="#1567d3" />
</View>
)
} else {
console.log("Loading False");
return (
<ScrollView scrollEnabled={true}>
<KeyboardAvoidingView behavior="padding" keyboardVerticalOffset={70}>
<View style={{ flex: 1 }}>
<View style={styles.logoSection}>
{/* <SvgComponent height={100} /> */}
<Icon name="ios-contact" size={90} color='#4d8dd6' style={{ marginTop: 9 }} />
<Text style={{ fontSize: 18, color: "#000", margin: 35, marginTop: 7 }}>
{currentUser.username}
</Text>
</View>
{/* //username */}
<View style={style.child}>
<Icon name="ios-contact" size={30} color='#4285f4' style={{ marginTop: 9 }} />
<TextInput
style={style.textInput}
autoCapitalize="words"
value={currentUser.username}
onChangeText={(username) => { this.setState(Object.assign(currentUser, { username: username })) }}
/>
</View>
{/* //Email */}
<View style={style.child}>
<Icon name="md-at" size={30} color='#4285f4' style={{ marginTop: 9 }} />
<TextInput
style={style.textInput}
keyboardType="email-address"
autoCapitalize="words"
value={currentUser.email}
onChangeText={
(email) => { this.setState(Object.assign(currentUser, { email: email })) }
}
/>
</View>
{/* //Password */}
<View style={style.child}>
<Icon name="md-lock" size={30} color='#4285f4' style={{ marginTop: 9 }} />
<TextInput
style={style.textInput}
autoCapitalize="words"
placeholder="current password"
value={this.state.currentPassword}
onChangeText={(currentPassword) => this.setState({ currentPassword })}
/>
</View>
<View style={style.child}>
<Icon name="md-lock" size={30} color='#4285f4' style={{ marginTop: 9 }} />
<TextInput
style={style.textInput}
autoCapitalize="words"
placeholder="New password"
value={this.state.newPassword}
onChangeText={(newPassword) => { this.setState({ newPassword }) }}
/>
</View>
{/* //Location */}
<View style={style.child}>
<Icon name="ios-navigate" size={30} color='#4285f4' style={{ marginTop: 9 }} />
<TextInput
style={style.textInput}
autoCapitalize="words"
placeholder="New City"
value={currentUser.city}
onChangeText={(city) => { this.setState(Object.assign(currentUser, { city: city })) }}
/>
</View>
<View style={style.child}>
<Icon name="ios-call" size={30} color='#4285f4' style={{ marginTop: 9 }} />
<TextInput
style={style.textInput}
autoCapitalize="words"
keyboardType="number-pad"
placeholder="New Mobile Number"
value={currentUser.mobileNumber}
onChangeText={(mobileNumber) => { this.setState(Object.assign(currentUser, { mobileNumber: mobileNumber })) }}
/>
</View>
{/* Logout
<TouchableOpacity style={style.logout} onPress={this._logout}>
<Icon name="md-power" size={25} color='#0496FF' style={{ marginTop: -2 }} />
<Text style={{ paddingLeft: 10 }}>Logout</Text>
</TouchableOpacity>
*/}
</View>
{/* Save */}
<TouchableOpacity onPress={this._updateProfileData}
style={[styles.button, style.saveBtn]}>
<Text style={styles.TextButton}>Save</Text>
</TouchableOpacity>
</KeyboardAvoidingView>
</ScrollView>
);
}
}
}
export default profileEdit;
I think you have two options, option add more variables to state which you can use to compare the new data with and option two use three boolean values, one for password, email and other.
Option 1
constructor(props) {
super(props);
this.state = {
currentPassword: "",
newPassword: "",
email: '',
currentUser: {
username: "",
email: "",
city: "",
mobileNumber: "",
},
username: '',
city: '',
mobileNumber: '',
data: {},
loading: true
}
}
_updateProfileData = async () => {
const { currentPassword, email, currentUser, newPassword,
mobileNumber, username, city } = this.state;
if (currentPassword === "") {
alert("please write your current password first!")
return;
}
if (email !== currentUser.email) {
// email changed update
await this.changeEmail();
}
if (newPassword !== currentPassword) {
// password changed update
await this.changePassword();
}
if (city !== currentUser.city || mobileNumber !== currentUser.mobileNumber || username !== currentUser.username) {
await this._updateData();
}
}
async componentDidMount() {
try {
const userId = firebase.auth().currentUser.uid;
await this.setState({ userId });
console.log("#uid", this.state.userId);
let recentPostsRef = firebase.database().ref(`users/${userId}`);
await recentPostsRef.once('value').then(snapshot => {
const currentUser = snapshot.val();
this.setState({ currentUser: currentUser, email: currentUser.email, username: currentUser.username, city: currentUser.city, mobileNumber: currentUser.mobileNumber, loading: false })
console.log(this.state.currentUser)
}).catch((error) => console.log("#error", error));
} catch (error) {
console.log("#CError", error);
}
}
Option 2, have three booleans, passwordChanged,emailChanged,otherChanged when the user types in one of the inputs, set the value to true and in your _updateProfileData check if the value is true, then update the value.
constructor(props) {
super(props);
this.state = {
currentPassword: "",
newPassword: "",
currentUser: {
username: "",
email: "",
city: "",
mobileNumber: "",
},
data: {},
// boolean values for email, password and other
passwordChanged: false,
emailChanged: false,
otherChanged: false,
loading: true
}
}
_updateProfileData = async () => {
const { currentPassword, passwordChanged, emailChanged, otherChanged } = this.state;
if (currentPassword === "") {
alert("please write your current password first!")
return;
}
if (emailChanged) {
// email changed update
await this.changeEmail();
}
if (passwordChanged) {
// password changed update
await this.changePassword();
}
if (otherChanged) {
await this._updateData();
}
}
Please do the following:
// You have to change the method _updateProfileData as following
_updateProfileData = async () => {
if (this.state.currentPassword === "") {
alert("please write your current password first!")
return;
} if (this.state.currentUser.email === "") {
alert("Email can't be blank")
return;
} if (this.state.currentUser.username === "") {
alert("Username can't be blank")
return;
} if (this.state.currentUser.city === "") {
alert("City can't be blank")
return;
} if (this.state.currentUser.mobileNumber === "") {
alert("Mobile number can't be blank")
return;
} else {
this._getCurrentUserData((oldUserData) => {
if(oldUserData.email !== this.state.currentUser.email) {
await this.changeEmail();
}
if(this.state.newPassword !== this.state.currentPassword) {
await this.changePassword();
}
if(oldUserData.username !== this.state.currentUser.username || oldUserData.city !== this.state.currentUser.city || oldUserData.mobileNumber !== this.state.currentUser.mobileNumber ) {
await this._updateData();
}
);
}
}
// You have to add this method in your component
_getCurrentUserData = (callBack) => {
AsyncStorage.getItem('#MyProfile:data')
.then(json => JSON.parse(json))
.then(currentUser => callBack(currentUser))
.catch(error => console.log('#error' + error));
}
here in my code I am using Fixheader and Searchbar, but I'm trying to put searchbar below header and Header should be fixed .
One more problem is there,After entering anything in search bar then data is coming on FlatList .
Please help me for that , When I'm writing in searchbar or header outside the its generating error .
import React, { Component } from "react";
import {
View,
Text,
TextInput,
FooterTab,
Button,
TouchableOpacity,
ScrollView,
StyleSheet,
ActivityIndicator,
Header,
FlatList
} from "react-native";
import { Icon } from "native-base";
import { createStackNavigator } from "react-navigation";
import { SearchBar } from "react-native-elements";
export default class RenderList extends Component {
static navigationOptions = {
title: "Selected Item",
header: null
};
constructor() {
super();
this.state = {
data: "",
loading: true,
search: "",
searchText: "",
filterByValue: ""
};
}
componentDidMount() {
this.createViewGroup();
}
createViewGroup = async () => {
try {
const response = await fetch("http://example.com",
{
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify({
password: "admin",
username: "admin",
viewall: "false",
id: [4],
startlimit: "0",
valuelimit: "10"
})
}
);
const responseJson = await response.json();
const { groupData } = responseJson;
this.setState({
data: groupData,
loading: false
});
} catch (e) {
console.error(e);
}
};
clickedItemText(clickedItem) {
this.props.navigation.navigate("Item", { item: clickedItem });
}
updateSearch = search => {
this.setState({ search });
};
keyExtractor = ({ id }) => id.toString();
keyExtractor = ({ name }) => name.toString();
renderItem = ({ item }) => (
<TouchableOpacity
style={styles.item}
activeOpacity={0.4}
onPress={() => {
this.clickedItemText(item);
}}
>
<Text style={styles.ListText}>Hospital Id {item.id}</Text>
<Text>Hospital Name {item.name}</Text>
</TouchableOpacity>
);
renderSeparator = () => {
return (
<View
style={{
height: 1,
width: "86%",
backgroundColor: "#CED0CE"
}}
/>
);
};
onSearchInputChange = text => {
const filterByValue = this.state.data.filter(x =>
x.name.toLowerCase().includes(text.toLowerCase())
);
this.setState({
searchText: text,
filterByValue
});
};
Render_FlatList_Sticky_header = () => {
var Sticky_header_View = (
<View style={styles.header_style}>
<Text style={{ textAlign: "center", color: "#000000", fontSize: 22 }}>
{" "}
FlatList Sticky Header{" "}
</Text>
</View>
);
return Sticky_header_View;
};
render() {
const { loading, data, filterByValue } = this.state;
return (
<ScrollView>
<View style={styles.container1}>
<SearchBar
lightTheme
onChangeText={this.onSearchInputChange}
value={this.state.searchText}
//onClearText={someMethod}
icon={{ type: "font-awesome", name: "search" }}
placeholder="Type Here..."
/>
{/* <TextInput style={styles.Searchbar}
onChangeText={this.onSearchInputChange}
value={this.state.searchText}
/> */}
{this.state.loading ? (
<ActivityIndicator size="large" />
) : (
<FlatList
renderItem={this.renderItem}
keyExtractor={this.keyExtractor}
ItemSeparatorComponent={this.renderSeparator}
data={filterByValue}
ListHeaderComponent={this.Render_FlatList_Sticky_header}
stickyHeaderIndices={[0]}
// ListHeaderComponent={this.render_FlatList_header}
/>
)}
</View>
</ScrollView>
);
}
}
I really can't see how I'm getting undefined is not object (evaluating 'ReactPropTypes.string) error in my iOS simulator. My code in the WebStorm IDE isn't throw me any errors. I've tried deleting my node_modules folder and then running npm install in Terminal because that usually solves most problems, but not in this case.
Here's Secured.js:
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { ScrollView, Text, View, Button } from 'react-native';
import { logout } from '../redux/actions/auth';
import DropdownMenu from 'react-native-dropdown-menu';
import Icon from './Icon';
class Secured extends Component {
render() {
var data = [["Choice 1"], ["Choice 2"], ["Choice 3"], ["Choice 4"]];
return(
<ScrollView style={{padding: 20}}>
<Icon/>
<Text style={{fontSize: 27}}>
{`Welcome ${this.props.username}`}
</Text>
<View style={{flex: 1}}>
<DropdownMenu style={{flex: 1}}
bgColor={"purple"} //the background color of the head, default is grey
tintColor={"white"} //the text color of the head, default is white
selectItemColor={"orange"} //the text color of the selected item, default is red
data={data}
maxHeight={410} // the max height of the menu
handler={(selection, row) => alert(data[selection][row])} >
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}} >
</View>
</DropdownMenu>
</View>
<View style={{margin: 20}}/>
<Button onPress={(e) => this.userLogout(e)} title="Logout"/>
</ScrollView>
);
}
}
const mapStateToProps = (state, ownProps) => {
return {
username: state.auth.username
};
}
const mapDispatchToProps = (dispatch) => {
return {
onLogout: () => { dispatch(logout()); }
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Secured);
Here's Login.js:
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { ScrollView, Text, TextInput, View, Button, StyleSheet } from 'react-native';
import { login } from '../redux/actions/auth';
import {AuthenticationDetails, CognitoUser, CognitoUserAttribute, CognitoUserPool} from '../lib/aws-cognito-identity';
const awsCognitoSettings = {
UserPoolId: 'something',
ClientId: 'something'
};
class Login extends Component {
constructor (props) {
super(props);
this.state = {
page: 'Login',
username: '',
password: ''
};
}
get alt () { return (this.state.page === 'Login') ? 'SignUp' : 'Login'; }
handleClick (e) {
e.preventDefault();
const userPool = new CognitoUserPool(awsCognitoSettings);
// Sign up
if (this.state.page === 'SignUp') {
const attributeList = [
new CognitoUserAttribute({ Name: 'email', Value: this.state.username })
];
userPool.signUp(
this.state.username,
this.state.password,
attributeList,
null,
(err, result) => {
if (err) {
alert(err);
this.setState({ username: '', password: '' });
return;
}
console.log(`result = ${JSON.stringify(result)}`);
this.props.onLogin(this.state.username, this.state.password);
}
);
} else {
const authDetails = new AuthenticationDetails({
Username: this.state.username,
Password: this.state.password
});
const cognitoUser = new CognitoUser({
Username: this.state.username,
Pool: userPool
});
cognitoUser.authenticateUser(authDetails, {
onSuccess: (result) => {
console.log(`access token = ${result.getAccessToken().getJwtToken()}`);
this.props.onLogin(this.state.username, this.state.password);
},
onFailure: (err) => {
alert(err);
this.setState({ username: '', password: '' });
return;
}
});
}
}
togglePage (e) {
this.setState({ page: this.alt });
e.preventDefault();
}
render() {
return (
<ScrollView style={{padding: 20}}>
{/*<Text style={styles.title}>Welcome!</Text>*/}
<TextInput
style={styles.pw}
placeholder=' Email Address'
autoCapitalize='none'
autoCorrect={false}
autoFocus={true}
keyboardType='email-address'
value={this.state.username}
onChangeText={(text) => this.setState({ username: text })} />
<TextInput
style={styles.pw}
placeholder=' Password'
autoCapitalize='none'
autoCorrect={false}
secureTextEntry={true}
value={this.state.password}
onChangeText={(text) => this.setState({ password: text })} />
<View style={{margin: 7}}/>
<Button onPress={(e) => this.handleClick(e)} title={this.state.page}/>
<View style={{margin: 7, flexDirection: 'row', justifyContent: 'center'}}>
<Text onPress={(e) => this.togglePage(e)} style={styles.buttons}>
{this.alt}
</Text>
</View>
</ScrollView>
);
}
}
const styles = StyleSheet.create({
title: {
fontSize: 27,
textAlign: 'center'
},
icon: {
position: 'absolute'
},
pw: {
paddingRight: 90,
justifyContent: 'flex-end',
marginBottom: 20,
backgroundColor: '#9b42f4',
height: 40,
borderWidth: 1,
borderRadius: 5
},
buttons: {
fontFamily: 'AvenirNext-Heavy'
}
});
const mapStateToProps = (state, ownProps) => {
return {
isLoggedIn: state.auth.isLoggedIn
};
}
const mapDispatchToProps = (dispatch) => {
return {
onLogin: (username, password) => { dispatch(login(username, password)); }
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Login);
Check this out, this looks like the issue you're having https://github.com/facebook/react-native/issues/14588#issuecomment-309683553
npm install react#16.0.0-alpha.12 solves the problem.