I've written this react-native component which is giving me a bad feeling that it's not as good as my expectations.
I want to make it look cleaner with smart and less code.
import React, { Component } from 'react';
import {
SafeAreaView,
View,
Text,
ScrollView,
TextInput,
TouchableOpacity,
ActivityIndicator
} from 'react-native';
// Axios
const axios = require('axios').default;
// Toast
import Toast from 'react-native-simple-toast';
// Redux
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { authenticate } from '../redux/actions/Actions';
// AsyncStorage
import AsyncStorage from '@react-native-community/async-storage';
// Style
import { style, textInput, button } from '../assets/Style';
class Register extends Component {
constructor(props) {
super(props);
this.state = {
first_name: '',
last_name: null,
username: '',
email: '',
password: '',
password_confirmation: '',
loading: false,
errors: {}
};
}
register() {
const { first_name, last_name, username, email, password, password_confirmation } = this.state;
this.setState({
loading: true,
errors: {}
});
axios.post('register', {
first_name,
last_name,
username,
email,
password,
password_confirmation
}).then(({data}) => {
axios.defaults.headers.common['Authorization'] = `Bearer ${data.token}`;
AsyncStorage.setItem('token', data.token).then(() => {
this.props.authenticate(true, {
user: data.user
});
});
}).catch(error => {
if (! error.response || (error.response && error.response.status !== 422)) {
Toast.show('An error occurred.');
} else {
this.setState({
errors: error.response.data.errors
});
}
}).finally(() => {
this.setState({ loading: false });
});
}
getMessages(field) {
const { errors } = this.state;
if (! errors[field])
return <></>;
return (
<>{ errors[field].map((item, index) => <Text style={ style.inlineDangerMessage } key={index}>{item}</Text>) }</>
);
}
render() {
const { loading, errors } = this.state;
const opacity = loading ? 0.5 : 1;
const disabled = loading ? true : false;
return (
<SafeAreaView style={ style.safeArea }>
<ScrollView contentContainerStyle={ [style.flexCenter] }>
<View style={{ width: '60%' }}>
<TextInput style={ [textInput.default, (errors.first_name && style.isInvalidBottomBorder)] } placeholder="First name" defaultValue="" onChangeText={(text) => this.setState({ first_name: text })} />
{ this.getMessages('first_name') }
<TextInput style={ [textInput.default, (errors.last_name && style.isInvalidBottomBorder), { marginTop: 10 }] } placeholder="Last name" defaultValue="" onChangeText={(text) => this.setState({ last_name: text })} />
{ this.getMessages('last_name') }
<TextInput style={ [textInput.default, (errors.username && style.isInvalidBottomBorder), { marginTop: 10 }] } placeholder="Username" defaultValue="" onChangeText={(text) => this.setState({ username: text })} />
{ this.getMessages('username') }
<TextInput style={ [textInput.default, (errors.email && style.isInvalidBottomBorder), { marginTop: 10 }] } placeholder="Email" defaultValue="" onChangeText={(text) => this.setState({ email: text })} />
{ this.getMessages('email') }
<TextInput style={ [textInput.default, (errors.password && style.isInvalidBottomBorder), { marginTop: 10 }] } placeholder="Password" defaultValue="" secureTextEntry={true} onChangeText={(text) => this.setState({ password: text })} />
{ this.getMessages('password') }
<TextInput style={ [textInput.default, (errors.password_confirmation && style.isInvalidBottomBorder), { marginTop: 10 }] } placeholder="Password confirmation" defaultValue="" secureTextEntry={true} onChangeText={(text) => this.setState({ password_confirmation: text })} />
{ this.getMessages('password_confirmation') }
<TouchableOpacity style={ [button.primary, style.flexCenter, {
marginTop: 10,
height: 40,
opacity
}] } onPress={() => this.register()} disabled={disabled}>
{ ! loading ?
<Text style={ [style.vazirBold, style.textCenter, { color: '#fff' }] }>Register</Text> :
<ActivityIndicator size="small" color="#fff" />
}
</TouchableOpacity>
<TouchableOpacity style={{ marginTop: 15 }} onPress={() => this.props.navigation.goBack()} disabled={loading}>
<Text style={ [button.link, style.textCenter] }>I already have an account!</Text>
</TouchableOpacity>
</View>
</ScrollView>
</SafeAreaView>
);
}
}
const mapStateToProps = (state) => {
const { redux } = state
return { redux }
};
const mapDispatchToProps = (dispatch) => (
bindActionCreators({
authenticate,
}, dispatch)
);
export default connect(mapStateToProps, mapDispatchToProps)(Register);