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.
Related
I want save all input values in redux with dispatch and with useSelector return all data that saved in redux , in redux I create an object and that object have many objects , but I can not return data from redux with useSelector :
import React , { useState } from 'react';
import { useForm } from 'react-hook-form';
import {ButtonForm} from '../../partComponents/button';
import Input from '../../partComponents/input';
import { createStore } from 'redux'
import { Link } from 'react-router-dom';
import {ActionCreators} from '../../redux/constants/profile';
import { reducer } from '../../redux/reducer/profile'
import { useDispatch , useSelector } from 'react-redux'
const Signin = () =>{
const dispatch = useDispatch();
const selector = useSelector(state => state.reducer);
const { register, handleSubmit, formState: { errors } } = useForm();
const onSubmit = data => {
dispatch(ActionCreators.addProfile(data))
// console.log(s.getState())
};
return(
<section className="section-signin">
<div className="app__header">
<img src={anarLogo} className="app__header--logo" alt="header logo" />
</div>
<form className='signin__form' onSubmit={handleSubmit(onSubmit)}>
<Input
register={register}
inputName='Email'
inputType='text'
inputClass='form__input--text'
inputPlaceholder='Email'
inputErrors = {errors}
inputLabel = 'email'
rules={{ required: true, minLength: 5
}}
/>
<Input
register={register}
inputName='Full Name'
inputType='text'
inputClass='form__input--text'
inputPlaceholder='Full Name'
inputErrors = {errors}
inputLabel = 'fullname'
rules={{ required: true, maxLength: 30, minLength: 3
}}
/>
<Input
register={register}
inputName='Username'
inputType='text'
inputClass='form__input--text'
inputPlaceholder='Username'
inputErrors = {errors}
inputLabel = 'username'
rules={{ required: true, maxLength: 20, minLength: 3
}}
/>
<Input
register={register}
inputName='Password'
inputType='password'
inputClass='form__input--password'
inputPlaceholder='Password'
inputErrors = {errors}
inputLabel = 'password'
rules={{ required: true, maxLength: 20, minLength: 8 ,
pattern: {
value: new RegExp("(?=.*[a-z])(?=.*[0-9])"),
message: 'Password must contain at least one letter or number'
}
}}
/>
<ButtonForm
buttonValue='Submit'
buttonType='submit'
buttonClass='form__button--white'
/>
<p className='signin__message'>Have an account? <Link className='signin__message--link' to='/login'>Log in</Link></p>
here I want print fullname of user that assigned in website:
<h1>hello {selector.profile.fullname}</h1>
</form>
</section>
)
}
my reducer file :
import { Types } from '../constants/actionTypes';
import { createStore } from 'redux'
const initialState = {
profile : {
email: '',
fullname: '',
username: '',
password: ''
},
formSubmitted: false
}
export const reducer = (state = initialState , action) => {
switch(action.type){
case Types.ADD_USER:
console.log('sing In' , action.payload.user);
return{
...state,
profile: action.payload.user,
formSubmitted: false
}
case Types.LOGIN:
console.log('login' , action.payload.user)
return{
...state,
profile: action.payload.user,
formSubmitted: false
}
case Types.FORM_SUBMITION_STATUS:
return {
...state,
formSubmitted: action.payload.status
}
default:
return state;
}
}
The selector returns a partial state, state => state.reducer has no meaning since your state doesn't have any reducer part.
Since you want to return all your state, just select it:
const state = useSelector(state => state);
state.profile.fullname
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.
Unit test code cannot read component "jsx" content
the test result is always "Received: 0"
This is a screenshot of the unit test result using enzyme and jest with react.js
//**************************************component.js*************************************************//
class NetworkConfig extends Component {
constructor() {
super();
this.state = {
dataDeviceConfig: {
dhcp: false,
macAddress: '',
ipAddress: '',
subMask: '',
dns: '',
gateway: '',
},
alertMessage: "",
loader: false
};
}
render() {
return (
<div>
{console.log("Diagnostic Data", this.state.dataDeviceConfig)}
<Form onSubmit={this.handleSubmit}>
<div className="sn-forms-settings">
<FormItem
label={<IntlMessages id="settings.label.DHCP" />}
>
{getFieldDecorator('dhcp', {
})(
<Switch ............... />
)}
</FormItem>
<FormItem
label={(
<span>
<IntlMessages id="settings.label.MacAdres" />
</span>
)}
>
{getFieldDecorator('macAddress', {
initialValue: this.state.dataDeviceConfig.macAddress
})(
<label name="macAddress">{this.state.dataDeviceConfig.macAddress}</label>
)}
</FormItem>
</div>
</Form>
</div>
);
}
}
const mapStateToProps = ({ settingSense, common }) => {
const { dataDeviceConfig } = settingSense;
const {
loader,
alertMessage,
showAlert,
alertMessageStatus,
alertMessageComponent
} = common;
return {
dataDeviceConfig,
loader,
alertMessage,
showAlert,
alertMessageStatus,
alertMessageComponent
}
};
const NetworkConfigForm = Form.create()(NetworkConfig);
export default injectIntl(connect(mapStateToProps, {
getDevicEtherConfigAction, setDevicEtherConfigAction
, showLoaderAction, hideAlertAction, hideLoaderAction
})(NetworkConfigForm));
//**************************************component.test.js**********************************************//
import React from 'react';
import Enzyme,{shallow,configur } from 'enzyme';
import EnzymeAdapter from 'enzyme-adapter-react-16';
import configureMockStore from 'redux-mock-store';
import NetworkConfigForm from '../../../.....................';
import {Input} from "antd";
import {mountWithIntl,shallowWithIntl} from '../../helpers/intl-enzyme-test-helper.js';
Enzyme.configure({
adapter: new EnzymeAdapter(),
disableLifecycleMethods: false
});
describe('Network Config Test', () => {
it('render NetworkConfig Component', () => {
const state = {
settingSense:{
dataDeviceConfig: {
dhcp: false,
macAddress: '',
ipAddress: '',
subMask: '',
dns: '',
gateway: '',
}
},
common:{
loader: false,
alertMessage:'',
showAlert: false,
alertMessageStatus:'MESSAGE_SUCCESS',
alertMessageComponent:'ALERT_DEVICE_ETHER_CONFIG'
}
};
const mockStore = configureMockStore();
const store = mockStore(state);
const wrapper = shallowWithIntl(<NetworkConfigForm store={store}/>).dive();
expect(wrapper.find('.sn-forms-settings').children().length).toEqual(2)
});
});
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)}
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]);