4
\$\begingroup\$

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);
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Mar 16, 2020 at 21:55
\$\endgroup\$

1 Answer 1

2
\$\begingroup\$
  1. You don't need to use if and <></> for conditional-rendering:

     getMessages(field) {
     const { errors } = this.state;
     return (
     errors[field] && errors[field].map((item, index) => (
     <Text style={style.inlineDangerMessage} key={index}>
     {item}
     </Text>
     ))
     )
     }
    
  2. You can reuse the TextInput since there are many of them:

    • build an array of what you need

      const field = [
       { id: "1", attr: "first_name", placeholder: "First name" },
       { id: "2", attr: "last_name", placeholder: "Last name" }
       // ...
      ];
      
    • write common function

       styleFunction = attrName => {
       const { errors } = this.state;
       return [textInput.default, errors[attrName] && style.isInvalidBottomBorder];
       };
      
    • and map the repeated components

      {field.map(item => (
       <>
       <TextInput
       style={this.styleFunction(item.attr)}
       placeholder={item.placeholder}
       defaultValue=""
       onChangeText={text => this.setState({ [item.attr]: text })}
       />
       {this.getMessages(item.attr)}
       </>
      ))}
      

I'm sure there are other places where can be improved. As far as my immediate view, that's what I have got.

All the code here:

Edit objective-cdn-rhh9y

Toby Speight
87.1k14 gold badges104 silver badges322 bronze badges
answered Mar 17, 2020 at 8:11
\$\endgroup\$
1
  • \$\begingroup\$ I just want to add one more thing create router classes for webservices rather than using axios everytime. \$\endgroup\$ Commented Jul 28, 2021 at 12:19

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.