React Native login form - reactjs

I am trying to create Login page in React native using functional component. But it is not working. As soon as enter any text throwing error. value is not changing.
import React from "react";
import { View, Button, Text } from "react-native";
import Inputs from "../../utils/Form/Input";
const LoginForm = () => {
const [formData, setForm] = React.useState({
email: {
value: "",
valid: false,
type: "textinput",
rules: {
isRequired: true,
isEmail: true
}
},
password: {
value: "",
valid: false,
type: "textinput",
rules: {
isRequired: true,
minLength: true
}
}
});
const handleChange = () => {
setForm({ ...formData });
console.log(formData.email);
};
return (
<View>
<Text>Login</Text>
<Inputs
placeholder="Enter email address"
placeholdercolor="red"
autoCapitalize={"none"}
keyboardType={"email-address"}
onChangeText={value => handleChange("email", value)}
value={formData.email.value}
type={formData.email.type}
/>
<Inputs
placeholder="Password"
placeholdercolor="red"
autoCapitalize={"none"}
type={formData.password.type}
value={formData.password.value}
onChangeText={value => setForm("password", value)}
/>
</View>
);
};
export default LoginForm;
Util file
import React from "react";
import { View, Button, TextInput, Picker, StyleSheet } from "react-native";
const Inputs = props => {
let template = null;
switch (props.type) {
case "textinput":
template = (
<TextInput {...props} style={[styles.input, props.overrideStyle]} />
);
break;
default:
return template;
}
return template;
};
const styles = StyleSheet.create({
input: {
width: "100%",
borderBottomWidth: 2,
borderBottomColor: "blue",
fontSize: 16,
padding: 5,
marginTop: 10
}
});
export default Inputs;

You are missing parameters in handleChange function. It should be
const handleChange = (key, value) => {
let data = formData;
data[key].value = value;
setForm(data);
console.log(formData.email);
};

your handleChange change function is not proper and producing error, change your handle change method to this function
const handleChange = (val, data) => {
if (val === 'email') {
setForm({
...formData,
email: {
...formData.email,
value: data,
},
});
} else {
setForm({
...formData,
password: {
...formData.password,
value: data,
},
});
}
};
and change your onChangeText prop of password input to
onChangeText={value => handleChange('password', value)}

Related

How to update an object key value based on other key value in Array of object in React?

I need to understand how we can update an object key value based on other key value in Array of object in React. Let' assume I have two different input field which is somehow link with the below formatted object, this object basically responsible for changing behavior of graph whenever I type something in input field. The below object passed into Graph component to show the changes whenever we type something in 2 input field.
import React, {useState} from "react";
import ReactDOM from "react-dom";
import { GaugeChart } from "#carbon/charts-react";
import "#carbon/charts/styles.css";
// in the data object graph behavior will update based on
input provided in two input field and that will happen based on group key value
const graphObj = {
data: [
{
"group": "value",
"value": 40
},
{
"group": "delta",
"value": 1000
}
],
options: {
"resizable": true,
"height": "250px",
"width": "100%",
"gauge": {
"type": "semi",
"status": "danger"
}
}
};
const App = () => {
const [graph, setGraph] = useState(graphObj);
const [formData, setFormData] = useState({
min: 40,
max: 1000
})
const handleChange = (e) => {
}
return (
<>
<GaugeChart
data={graph.data}
options={graph.options}>
</GaugeChart>
<br />
<form>
<input value={formData.min} onChange={handleChange} />
<input value={formData.max} onChange={handleChange}/>
</form>
</>
);
}
export default App;
ReactDOM.render(<App />, document.getElementById("root"));
Assuming that min in your state is value and max is delta, I would refactor a bit. Since your graphObj is a constant that we just want to add the formData to we can use useMemo that we remake the graphOptions object everytime form data updates.
import React, { useState, useMemo } from "react";
import ReactDOM from "react-dom";
import { GaugeChart } from "#carbon/charts-react";
import "#carbon/charts/styles.css";
const graphObj = {
data: [
{
group: "value",
value: 40,
},
{
group: "delta",
value: 1000,
},
],
options: {
resizable: true,
height: "250px",
width: "100%",
gauge: {
type: "semi",
status: "danger",
},
},
};
const App = () => {
const [formData, setFormData] = useState({
value: 40,
delta: 1000,
});
const handleChange = (e) => {
const { name, value } = e.target;
// update the form data
setFormData({ ...formData, [name]: value });
};
// add form data to graph object
const graphData = useMemo(() => {
// formdata to { group: key, value: value } type
return Object.keys(formData).map((key) => ({
group: key,
value: formData[key],
}));
}, [formData]);
return (
<>
<GaugeChart data={graphData} options={graphObj.options}></GaugeChart>
<br />
<form>
<input name={"value"} value={formData.value} onChange={handleChange} />
<input name={"delta"} value={formData.delta} onChange={handleChange} />
</form>
</>
);
};
export default App;

React-native TypeError: Cannot read property 'data' of undefined

I have propblems in my project
enter image description here
D:\React-Native\Expo\mobile\node_modules\expo\build\logs\RemoteConsole.js:80 Possible Unhandled Promise Rejection (id: 0):
TypeError: Cannot read property 'data' of undefined
TypeError: Cannot read property 'data' of undefined
SignUp.js
import React from 'react';
import {ScrollView, KeyboardAvoidingView, CheckBox, View, Text, Platform,} from 'react-native';
import styles from './styles/authStyles';
import ScreenTitle from '../components/ScreenTitle';
import Input from '../components/input';
import Button from '../components/Button';
import axios from '../config/axios';
import { SINGNUP_URL } from '../config/urls';
import Loader from '../components/Loader';
import Alert from '../components/Alert';
export default class SignUpScreen extends React.Component
{
constructor(props)
{
super(props);
this.state =
{
name: "",
email: "",
password: "",
specialization: "",
phone: "",
address: "",
workingHours: "",
userType: false,
location: null,
isLoading: false,
alert:
{
messages: null,
type: "",
}
}
}
componentDidUpdate()
{
if(this.state.alert.messages)
{
setTimeout(() =>
{
this.setState({alert: {messages: null}})
}, 3000)
}
}
componentWillUnMount()
{
clearTimeout();
}
changeNameHandler = (value) =>
{
this.setState({name: value})
};
changeEmailHandler = (value) =>
{
this.setState({email: value})
};
changePasswordHandler= (value) =>
{
this.setState({password: value})
};
changeSpecializationHandler = (value) =>
{
this.setState({specialization: value})
};
changePhoneHandler = (value) =>
{
this.setState({phone: value})
};
changeAddressHandler = (value) =>
{
this.setState({address: value })
};
changeWorkingHoursHandler = (value) =>
{
this.setState({workingHours: value})
};
changeUserTypeHandler = () =>
{
this.setState({ userType: !this.state.userType})
}
validate()
{
const {name, email, password, specialization, address, phone, workingHours, userType} = this.state;
let validationErrors = [];
let passed = true;
if(!name)
{
validationErrors.push(" Please put your name");
passed= false;
}
if(!email)
{
validationErrors.push(" Please put your email");
passed= false;
}
if(!password)
{
validationErrors.push(" Please put your password");
passed= false;
}
if(userType)
{
if(!specialization)
{
validationErrors.push(" Please put your specialization");
passed= false;
}
if(!address)
{
validationErrors.push(" Please put your address");
passed= false;
}
if(!phone)
{
validationErrors.push(" Please put your phone nuber");
passed= false;
}
if(!workingHours)
{
validationErrors.push(" Please put your working hours");
passed= false;
}
}
if(validationErrors.length > 0)
{
this.setState({alert: {messages: validationErrors, type: "danger"}})
}
return passed
}
_SignUp = async () =>
{
if(!this.validate()) return;
this.setState({isLoading: true})
const { name, email, password, specialization, address, phone, workingHours, userType } = this.state;
const body =
{
name,
email,
password,
specialization,
address,
phone,
workingHours,
userType: userType ? "doctor" : 'normal',
location:
{
latitude: 1,
longitude: 2
},
isLoading: false
}
try
{
const response = await axios.post(SINGNUP_URL, body);
this.setState({
name:'',
email: '',
password: '',
specialization: '',
address: '',
phone: '',
workingHours: '',
userType: false,
location: null
});
this.props.navigation.navigate("SignIn",
{
alert:{messages:"Your account has been successfully registered", type:"success"}
});
}
catch(e){
this.setState({
alert: { messages: e.response.data.message, type: "danger"},
isLoading: false
});
}
}
render()
{
const { name, email, password, specialization, address, phone, workingHours, userType, isLoading, alert } = this.state;
return(
<ScrollView contentContainerStyle={{paddingVertical: 40}}>
<Loader title="A new account is creating" loading={isLoading} />
<Alert messages={alert.messages} type={alert.type} />
<View style={styles.container}>
<ScreenTitle
title="Create new account"
icon="md-person-add"
/>
<KeyboardAvoidingView behavior="padding" enabled >
<Input
placeholder="Name"
onChangeText={this.changeNameHandler}
value={name} />
<Input
placeholder="Email"
onChangeText={this.changeEmailHandler}
value={email} />
<Input
placeholder="Password"
secureTextEntry
onChangeText={this.changePasswordHandler}
value={password} />
<View
style={styles.checkBoxContainer}
>
<CheckBox
style={styles.checkBoxLabel}
value={userType}
onChange={this.changeUserTypeHandler} />
<Text style={styles.checkBoxLabel} >Doctors</Text>
</View>
{userType && (
<React.Fragment>
<Input
onChangeText={this.changeSpecializationHandler}
placeholder="Specialization" value = {specialization} />
<Input
onChangeText={this.changeWorkingHoursHandler}
placeholder="Hours work" value={workingHours} />
<Input
onChangeText={this.changeAddressHandler}
placeholder="Address" value={address} />
<Input
onChangeText={this.changePhoneHandler}
placeholder="Phone Number" value={phone} />
</React.Fragment>
)}
<Button
text="New Account"
onPress={this._SignUp}
/>
<View style={{height: 30}} />
{/* <Button text="Home" onPress={() => this.props.navigation.navigate("Main")} /> */}
</KeyboardAvoidingView>
</View>
</ScrollView>
)
}
}
SignIn.js
import React, { Component } from 'react'
import { Text, View, KeyboardAvoidingView, AsyncStorage } from 'react-native'
import styles from './styles/authStyles';
import ScreenTitle from '../components/ScreenTitle';
import Input from '../components/input';
import Button from '../components/Button';
import axios from '../config/axios';
import { SIGNIN_URL } from '../config/urls';
import Loader from '../components/Loader';
import Alert from '../components/Alert';
import Container from '../components/Container';
import { ScrollView } from 'react-native-gesture-handler';
export default class SignIn extends Component {
constructor(props)
{
super(props);
this.state =
{
email: "",
password: "",
isLoading: false,
alert:
{
messages: null,
type: ""
}
}
}
componentDidMount()
{
const alert = this.props.navigation.getParam('alert');
if(alert)
{
this.setState({alert});
}
}
componentDidUpdate()
{
if(this.state.alert.messages)
{
setTimeout(() =>
{
this.setState({alert: {messages: null}})
}, 3000)
}
}
componentWillUnMount()
{
clearTimeout();
}
changeEmailHandler = (value) =>
{
this.setState({email: value})
};
changePasswordHandler= (value) =>
{
this.setState({password: value})
};
validate()
{
const { email, password } = this.state;
let validationErrors = [];
let passed = true;
if(!email)
{
validationErrors.push(" Please put your email");
passed= false;
}
if(!password)
{
validationErrors.push(" Please put your password");
passed= false;
}
if(validationErrors.length > 0)
{
this.setState({alert: {messages: validationErrors, type: "danger"}})
}
return passed
}
_SignIn= async () => {
if(!this.validate()) return;
this.setState({ isLoading: true });
const body = {
email: this.state.email,
password: this.state.password
};
try {
const response = await axios.post(SIGNIN_URL, body);
this.setState({ email: "", password: "", isLoading: false });
AsyncStorage.setItem("accessToken", response.data.accessToken);
} catch (e) {
this.setState({
alert: { messages: e.response.data.message, type: "danger" },
isLoading: false
});
}
}
render() {
const {email, password, isLoading, alert} = this.state;
return (
<Container>
<Alert messages={alert.messages} type={alert.type} />
<Loader title="Login" loading={isLoading} />
<ScrollView
keyboardShouldPersistTaps="handled"
contentContainerStyle={styles.container} >
<ScreenTitle title="Login" icon="md-log-in" />
<KeyboardAvoidingView behavior="padding" enabled>
<Input
onChangeText={this.changeEmailHandler}
value={email}
placeholder="Email" />
<Input
onChangeText={this.changePasswordHandler}
value={password}
secureTextEntry
placeholder="Password" />
</KeyboardAvoidingView>
<Button
text="Login"
onPress={this._SignIn}
/>
<View style={{height: 30}} />
{/* <Button text="Home" onPress={() => this.props.navigation.navigate("Main")} /> */}
</ScrollView>
</Container>
)
}
}
Try changing
catch (e) {
this.setState({
alert: { messages: e.response.data.message, type: "danger" },
isLoading: false
});
}
To
catch (e) {
let {response: {data: {message = ''} = {}} = {}} = e
this.setState({
alert: { messages: message, type: "danger" },
isLoading: false
});
}
And before even doing that please check the value of e using console.log and make sure message exist in the nested object.

React Native TypeError undefined is not an object

I'm new to React Native and trying to build a simple app where the user can change their user info. My problem starts when I'm trying to load the already existing data into my form, sometimes I'm getting this error: undefined is not an object result[0].first_name, but not always.
here's my snack
thanks in advance
here's my code:
//Action
import { FETCH_USER, UPDATE_USER } from './actionTypes';
export const fetchUser = () => {
return async (dispatch, getState) => {
const url = 'https://reqres.in/api/users?page=1';
const response = await fetch(url, {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
}
});
if(!response.ok){
const errorResData = await response.json();
console.log('error', response);
let message = "error";
throw new Error(message);
}
const resData = await response.json();
dispatch({ type: FETCH_USER, data: resData.data });
};
};
my reducer
import { FETCH_USER } from '../actions/actionTypes';
const initialState = {
data: [],
};
export default (state = initialState, action) => {
switch (action.type) {
case FETCH_USER:
return {
data: action.data
};
default:
return state;
}
};
component
import { useDispatch, useSelector } from 'react-redux';
import Style from '../../constants/Style';
import Input from '../../components/UI/Input/Input';
import Button from '../../components/UI/Button/Button';
import Textarea from '../../components/UI/Textarea/Textarea';
import * as userActions from '../../store/actions/user';
const FORM_INPUT_UPDATE = 'FORM_INPUT_UPDATE';
const FROM_INITIAL_VALUE = 'FROM_INITIAL_VALUE';
const formReducer = (state, action) => {
if (action.type === FORM_INPUT_UPDATE) {
const updatedValues = {
...state.inputValues,
[action.input]: action.value,
};
const updatedValidities = {
...state.inputValidties,
[action.input]: action.isValid,
};
let updatedFormIsValid = true;
for (const key in updatedValidities) {
updatedFormIsValid = updatedFormIsValid && updatedValidities[key];
}
return {
formIsValid: updatedFormIsValid,
inputValidties: updatedValidities,
inputValues: updatedValues,
};
}
if (action.type === FROM_INITIAL_VALUE) {
return {
...state,
inputValues: action.initialValues,
};
}
return state;
};
const ChangeAccount = props => {
const [error, setError] = useState();
const [refresh, setRefresh] = useState(false);
const dispatch = useDispatch();
const result = useSelector(state => {
return state.user.data.filter(state => state.id == 1);
});
const [formState, dispatchFormState] = useReducer(formReducer, {
inputValues: {
firstname: '',
lastname: '',
email: '',
password: '',
passwordAgain: '',
},
inputValidties: {
firstname: false,
lastname: false,
email: false,
password: false,
passwordAgain: false,
},
formIsValid: false,
});
const inputChangeHandler = useCallback(
(inputIdentifier, inputValue, inputValidity) => {
dispatchFormState({
type: FORM_INPUT_UPDATE,
value: inputValue,
isValid: inputValidity,
input: inputIdentifier,
});
},
[dispatchFormState]
);
const loadUser = useCallback(async () => {
setError(null);
try {
await dispatch(userActions.fetchUser()).then(() => {
setRefresh(false);
});
} catch (err) {
setError(err.message);
}
}, [dispatch, setError]);
const saveHandler = useCallback(async() => {
alert(formState.inputValues.firstname);
});
useEffect(() => {
setRefresh(true);
loadUser();
}, []);
useEffect(() => {
console.log('loadedData', result);
my error points to the code below
dispatchFormState({
type: FROM_INITIAL_VALUE,
initialValues: {
firstname: result[0].first_name,
lastname: result[0].last_name,
email: result[0].email,
},
});
}, [refresh, dispatchFormState]);
if (!refresh) {
return (
<View style={{ flex: 1, backgroundColor: Style.Colors.lightWhite }}>
<View style={styles.header}>
<Textarea Color={'rgb(77,77,77)'} Size={29.5}>
Settings
</Textarea>
</View>
<View style={styles.heading}>
<Textarea Color={'rgb(77,77,77)'} Size={22.1}>
Account
</Textarea>
</View>
<View
style={{
width: wp('100%'),
justifyContent: 'space-between',
alignItems: 'center',
marginTop: 30,
height: hp('40%'),
}}>
<Input
style={Style.lightInputStyle}
id="firstname"
label="Firstname"
labelColor="rgb(157,157,186)"
errorText="Check firstname"
autoCapitalize="none"
autoCorrect={false}
keyboardType="default"
onInputChange={inputChangeHandler}
initialValue={formState.inputValues.firstname}
initiallyValid={false}
required
/>
<Input
style={Style.lightInputStyle}
id="lastname"
label="Lastname"
labelColor="rgb(157,157,186)"
errorText="Check lastname"
autoCapitalize="none"
autoCorrect={false}
keyboardType="default"
onInputChange={inputChangeHandler}
initialValue={formState.inputValues.lastname}
initiallyValid={false}
required
/>
<Input
style={Style.lightInputStyle}
id="email"
label="Email"
labelColor="rgb(157,157,186)"
errorText="Check email"
autoCapitalize="none"
autoCorrect={false}
keyboardType="default"
onInputChange={inputChangeHandler}
initialValue={formState.inputValues.email}
initiallyValid={false}
required
/>
<Input
style={Style.lightInputStyle}
id="password"
label="Password"
labelColor="rgb(157,157,186)"
errorText="Check password"
autoCapitalize="none"
autoCorrect={false}
keyboardType="default"
onInputChange={inputChangeHandler}
required
/>
<Input
style={Style.lightInputStyle}
id="passwordAgain"
label="Password (again)"
labelColor="rgb(157,157,186)"
errorText="Check password (again)"
autoCapitalize="none"
autoCorrect={false}
keyboardType="default"
onInputChange={inputChangeHandler}
required
/>
</View>
<View
style={{
width: wp('100%'),
alignItems: 'center',
marginTop: hp('10%'),
}}>
<Button
BtnStyle={Style.lightPurpleButton}
Color={Style.Colors.lightWhite}
Size={Style.FontSize.btn}
OnPress={saveHandler}>
Save
</Button>
</View>
</View>
);
} else {
return (
<View style={{ flex: 1, backgroundColor: Style.Colors.lightWhite }}>
<Text>Loading</Text>
</View>
);
}
};
const styles = StyleSheet.create({
header: {
marginTop: 20,
marginLeft: '7%',
},
heading: {
marginTop: 30,
marginLeft: '7%',
},
});
export default ChangeAccount;
It seems to me that you're not checking your result and specifically you're not checking if result[0] is populated when you trigger the dispatchFormState, you're probably trying to populate the form before your result is actually loaded. Also, you should check your refresh variable in order to perform the dispatch only when data is not refreshing.
Try this:
useEffect(() => {
console.log('loadedData', result);
if (!refresh && result[0]) {
dispatchFormState({
type: FROM_INITIAL_VALUE,
initialValues: {
firstname: result[0].first_name,
lastname: result[0].last_name,
email: result[0].email,
},
});
}
}, [refresh, dispatchFormState]);

How to render only 5 items in react autosuggest?

I'am using react autosuggest npm package to get the json data and display it. I want to display only 5 items. How to do it?
Form.js
import React from 'react'
import Autosuggest from 'react-autosuggest';
import cities from 'cities.json';
const getSuggestions = value => {
const inputValue = value.trim().toLowerCase();
const inputLength = inputValue.length;
// Here I get data from cities.json
return inputLength === 0 ? [] : cities.filter(lang =>
lang.name.toLowerCase().slice(0, inputLength) === inputValue
);
);
};
const getSuggestionValue = suggestion => suggestion.name;
const renderSuggestion = suggestion => (
<div>
{console.log('suggestion', suggestion)}
{suggestion.name}
</div>
);
class Form extends React.Component {
constructor() {
super();
this.state = {
value: '',
suggestions: []
};
}
onChange = (event, { newValue }) => {
this.setState({
value: newValue
});
};
onSuggestionsFetchRequested = ({ value }) => {
this.setState({
suggestions: getSuggestions(value)
});
};
onSuggestionsClearRequested = () => {
this.setState({
suggestions: []
});
};
render(){
const { value, suggestions } = this.state;
// Autosuggest will pass through all these props to the input.
const inputProps = {
placeholder: 'Search City...',
value,
onChange: this.onChange
};
return (
<div>
<Autosuggest
suggestions={suggestions}
onSuggestionsFetchRequested={this.onSuggestionsFetchRequested}
onSuggestionsClearRequested={this.onSuggestionsClearRequested}
getSuggestionValue={getSuggestionValue}
renderSuggestion={renderSuggestion}
inputProps={inputProps}
/>
<br/>
</div>
)
}
}
export default Form;
I want to render only 5 items, otherwise, computer hangs while loading huge data. Is there any other autocomplete react npm package, since I want only cities and country list. i.e when city is inputted, automatically the city name must be suggested with its relevant country.Any solution or suggestion highly appreciated. Thanks in advance
i modified you're getSuggestions() method a little i guess this should work for you.
const getSuggestions = value => {
const inputValue = value.trim().toLowerCase();
const inputLength = inputValue.length;
// Here I get data from cities.json
return inputLength === 0 ? [] : cities.filter(lang =>
lang.name.toLowerCase().slice(0, inputLength) === inputValue
).slice(0,5);
};
Use the Slice method with start index and last Index
suggestions={suggestions.slice(0, 5)}
import {
React
,Avatar
,axiosbase
} from '../../import-files';
import Autosuggest from 'react-autosuggest';
import './autosuggest.css';
import { withStyles } from '#material-ui/core/styles';
import TextField from '#material-ui/core/TextField';
import Paper from '#material-ui/core/Paper';
import MenuItem from '#material-ui/core/MenuItem';
let suggestions = [ { label: 'Afghanistan' } ];
function renderInputComponent(inputProps) {
const { classes, inputRef = () => {}, ref, ...other } = inputProps;
return (
<TextField
className={classes.textField}
fullWidth
variant="outlined"
InputProps={{
inputRef: node => {
ref(node);
inputRef(node);
},
classes: {
input: classes.input,
},
}}
{...other}
/>
);
}
function renderSuggestion(suggestion, { query, isHighlighted }) {
return (
<MenuItem selected={isHighlighted} component="div">
<div>
<strong key={String(suggestion.id)} style={{ fontWeight: 300 }}>
<span className="sugg-option">
<span className="icon-wrap">
<Avatar src={suggestion.Poster}></Avatar>
</span>
<span className="name">
{suggestion.Title}
</span>
</span>
</strong>
</div>
</MenuItem>
);
}
function initSuggestions(value) {
suggestions = value;
}
function getSuggestionValue(suggestion) {
return suggestion.Title;
}
function onSuggestionSelected(event, { suggestion, suggestionValue, suggestionIndex, sectionIndex, method }) {
console.log('HandleSuggestion() '+suggestionValue);
}
const styles = theme => ({
root: {
height: 50,
flexGrow: 1,
},
container: {
position: 'relative',
},
suggestionsContainerOpen: {
position: 'absolute',
zIndex: 998,
marginTop: theme.spacing.unit,
left: 0,
right: 0,
overflowY: 'scroll',
maxHeight:'376%'
},
suggestion: {
display: 'block',
},
suggestionsList: {
margin: 0,
padding: 0,
listStyleType: 'none',
},
divider: {
height: theme.spacing.unit * 2,
},
});
class IntegrationAutosuggest extends React.Component {
state = {
single: '',
popper: '',
suggestions: [],
};
componentDidMount() {
initSuggestions(suggestions);
}
// Filter logic
getSuggestions = async (value) => {
const inputValue = value.trim().toLowerCase();
var _filter = JSON.stringify({
filter : inputValue,
});
return await axiosbase.post(`${apiCall}`, _filter);
};
handleSuggestionsFetchRequested = ({ value }) => {
this.getSuggestions(value)
.then(data => {
if (data.Error) {
this.setState({
suggestions: []
});
} else {
const responseData = [];
data.data.itemsList.map((item, i) => {
let File = {
id: item.idEnc,
Title: item.englishFullName +' '+item.arabicFullName,
englishFullName: item.englishFullName,
arabicFullName: item.arabicFullName,
Poster: item.photoPath,
}
responseData.push(File);
});
this.setState({
suggestions: responseData
});
}
})
};
handleSuggestionsClearRequested = () => {
this.setState({
suggestions: [],
});
};
handleChange = name => (event, { newValue }) => {
this.setState({
[name]: newValue,
});
if(event.type=='click'){
if(typeof this.props.handleOrderUserFirstNameChange === "function"){
this.props.handleOrderUserFirstNameChange(newValue);
}
this.state.suggestions.filter(f=>f.Title===newValue).map((item, i) => {
//id
//Title
// Poster
if(typeof this.props.handleUserIDChange === "function"){
this.props.handleUserIDChange(item.id);
}
});
}
};
render() {
const { classes } = this.props;
// console.log('Re-render!!');
// console.log(this.props);
// console.log(this.state.suggestions);
const autosuggestProps = {
renderInputComponent,
suggestions: this.state.suggestions,
onSuggestionsFetchRequested: this.handleSuggestionsFetchRequested,
onSuggestionsClearRequested: this.handleSuggestionsClearRequested,
onSuggestionSelected: this.props.onSelect,
getSuggestionValue,
renderSuggestion,
};
return (
<div className={classes.root}>
<Autosuggest
{...autosuggestProps}
inputProps={{
classes,
placeholder: this.props.placeHolder,
value: this.state.single,
onChange: this.handleChange('single'),
}}
theme={{
container: classes.container,
suggestionsContainerOpen: classes.suggestionsContainerOpen,
suggestionsList: classes.suggestionsList,
suggestion: classes.suggestion,
}}
renderSuggestionsContainer={options => (
<Paper {...options.containerProps} square>
{options.children}
</Paper>
)}
/>
<div className={classes.divider} />
</div>
);
}
}
export default withStyles(styles)(IntegrationAutosuggest);

React Native Store value in redux

i wanted to store the Email in the redux store and i am unable to do so here is my sign in component and redux store any help would be appreciated i am using react-navigation
My Dispatch Method is invoked on the initial load as well as on every key stroke for email input i want that to invoke only on hit of continue button
I need a way to store the email in the store and retrieve it in some other screen later
SignUp.js
import React, { Component } from 'react';
import {
StyleSheet,
View,
KeyboardAvoidingView,
Keyboard,
TouchableWithoutFeedback,
Alert
} from 'react-native';
import { SocialIcon } from 'react-native-elements';
import PropTypes from 'prop-types';
import { Header } from 'react-navigation';
import { connect } from 'react-redux';
import {
Container, Footer, FooterContainer, DefaultInput, Typography
} from '../components/common';
import { validate } from '../config';
import * as actionTypes from '../store/actions';
const styles = StyleSheet.create({
container: {
flex: 1
},
input: {
width: '80%',
height: 40
}
});
class SignUp extends Component {
state = {
controls: {
email: {
value: '',
valid: false,
validationRules: {
isEmail: true
},
touched: false
},
password: {
value: '',
valid: false,
validationRules: {
minLength: 6
},
touched: false
},
confirmPassword: {
value: '',
valid: false,
validationRules: {
equalTo: 'password'
},
touched: false
}
}
};
updateInputState = (key, value) => {
let connectedValue = {};
const stateObject = this.state;
if (stateObject.controls[key].validationRules.equalTo) {
const equalControl = stateObject.controls[key].validationRules.equalTo;
const equalValue = stateObject.controls[equalControl].value;
connectedValue = {
...connectedValue,
equalTo: equalValue
};
}
if (key === 'password') {
connectedValue = {
...connectedValue,
equalTo: value
};
}
this.setState(prevState => ({
controls: {
...prevState.controls,
confirmPassword: {
...prevState.controls.confirmPassword,
valid:
key === 'password'
? validate(
prevState.controls.confirmPassword.value,
prevState.controls.confirmPassword.validationRules,
connectedValue
)
: prevState.controls.confirmPassword.valid
},
[key]: {
...prevState.controls[key],
value,
valid: validate(value, prevState.controls[key].validationRules, connectedValue),
touched: true
}
}
}));
};
render () {
const stateData = this.state;
const { navigation } = this.props;
return (
<KeyboardAvoidingView
style={styles.container}
behavior="padding"
keyboardVerticalOffset={Header.HEIGHT + 20}
>
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
<Container>
<Typography textType="loginLabelStyle" textLabel="Use any of your existing profiles" />
<View style={‌{
flexDirection: 'row',
justifyContent: 'space-between',
}}
>
<SocialIcon type="twitter" />
<SocialIcon type="facebook" />
<SocialIcon type="google" light onPress={this.signIn} />
</View>
<Typography textType="loginLabelStyle" textLabel="or create one on SimpliFid" />
<DefaultInput
placeholder="Your E-Mail Address"
style={styles.input}
value={stateData.controls.email.value}
onChangeText={val => this.updateInputState('email', val)}
valid={stateData.controls.email.valid}
touched={stateData.controls.email.touched}
autoCapitalize="none"
autoCorrect={false}
keyboardType="email-address"
/>
<DefaultInput
placeholder="Password"
style={styles.input}
value={stateData.controls.password.value}
onChangeText={val => this.updateInputState('password', val)}
valid={stateData.controls.password.valid}
touched={stateData.controls.password.touched}
secureTextEntry
/>
<DefaultInput
placeholder="Confirm Password"
style={styles.input}
value={stateData.controls.confirmPassword.value}
onChangeText={val => this.updateInputState('confirmPassword', val)}
valid={stateData.controls.confirmPassword.valid}
touched={stateData.controls.confirmPassword.touched}
secureTextEntry
/>
<FooterContainer>
<Footer
leftButtonHandler={() => navigation.goBack()}
rightButtonHandler={this.props.onSignUp(stateData.controls.email.value, navigation)}
/* rightButtonHandler={() => navigation.navigate('ChatBot')} */
/>
</FooterContainer>
</Container>
</TouchableWithoutFeedback>
</KeyboardAvoidingView>
);
}
}
SignUp.propTypes = {
navigation: PropTypes.shape({
navigate: PropTypes.func.isRequired
}).isRequired
};
const mapDispatchToProps = dispatch => ({
onSignUp: (email, navigation) => {
Alert.alert(email);
dispatch({ type: actionTypes.SIGNUP, email });
navigation.navigate('ChatBot');
}
});
export default connect(
null,
mapDispatchToProps
)(SignUp);
Reducers.js
import * as actionTypes from './actions';
const initialState = {
email: '',
accountType: '',
name: '',
dob: '',
address: '',
ssn: '',
phoneNumber: '',
};
const reducer = (state = initialState, action) => {
switch (action.type) {
case actionTypes.SIGNUP:
return {
...state,
email: action.email,
};
default:
return state;
}
};
export default reducer;
You are calling the this.props.onSingUp methods on each render
Try wrapping the call in a handler method:
handleRightButton = () => {
this.props.onSignUp(this.state..controls.email.value, this.props.navigation);
}
// And on render
render() {
...
rightButtonHandler={this.handleRightButton}
...
}
The problem was that i was trying to access the store in a wrong way i was trying using this
import state from '../store/reducers';
const Email = state.email;
However the correct way and probably the only way to access the store is using mapStateToProps
const mapStateToProps = state => ({
email: state.email,
});
<Footer
leftButtonHandler={() => navigation.goBack()}
rightButtonHandler={(event) => {
event.preventDefault();
this.props.onSignUp(stateData.controls.email.value,navigation)
/>
Try adding the event.preventDefault() in the rightButtonHandler.

Resources