From 1d66f1dfe3661745999ce96414979150a3331069 Mon Sep 17 00:00:00 2001 From: Nikolai R Kristiansen Date: Tue, 5 Oct 2021 23:04:21 +0200 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=20Refactor=20UserRegister=20into=20se?= =?UTF-8?q?miworking=20state?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Navigation.js | 4 +- src/modules/register/UserRegister.js | 309 ++++++++---------- src/modules/register/UserRegisterContainer.js | 47 --- src/modules/register/useUserRegister.js | 29 ++ src/screens/UserRegisterScreen.js | 13 - 5 files changed, 170 insertions(+), 232 deletions(-) delete mode 100644 src/modules/register/UserRegisterContainer.js create mode 100644 src/modules/register/useUserRegister.js delete mode 100644 src/screens/UserRegisterScreen.js diff --git a/src/Navigation.js b/src/Navigation.js index eab13ba..57ead87 100644 --- a/src/Navigation.js +++ b/src/Navigation.js @@ -6,11 +6,11 @@ import Icon from 'react-native-vector-icons/SimpleLineIcons'; import EventListScreen from './screens/EventListScreen'; import EventDetailScreen from './screens/EventDetailScreen'; -import UserRegisterScreen from './screens/UserRegisterScreen'; import Membership from './modules/membership/Membership'; import Login from './modules/login/Login'; import AboutContainer from './modules/about/AboutContainer'; +import UserRegister from './modules/register/UserRegister'; const EventStack = createNativeStackNavigator(); const EventStackScreen = () => ( @@ -37,7 +37,7 @@ const UserStackScreen = () => ( { + const [firstName, setFirstName] = useState(''); + const [lastName, setLastName] = useState(''); + const [email, setEmail] = useState(''); + const [phoneNumber, setPhoneNumber] = useState(''); + const [password, setPassword] = useState(''); + const [errors, setErrors] = useState({}); + const [touched, setTouched] = useState(new Set()); + const { isRegisteringUser, onRegisterPress } = useUserRegister(); - this.state = { - firstName: '', - lastName: '', - email: '', - phoneNumber: '', - password: '', - errors: {}, - touched: new Set(), - }; - } + const emailInputRef = useRef(); + const lastNameInputRef = useRef(); + const phoneInputRef = useRef(); + const passwordInputRef = useRef(); - validateForm(triggeredBy) { - const fieldNames = ['firstName', 'lastName', 'email', 'phoneNumber', 'password']; + const validateForm = (triggeredBy) => { + const values = { firstName, lastName, email, phoneNumber, password }; - const errors = { ...this.state.errors }; - const touched = new Set(this.state.touched).add(triggeredBy); + const freshErrors = { ...errors }; + const freshTouched = new Set(touched).add(triggeredBy); /* No empty fields */ - fieldNames.forEach((key) => { - const value = this.state[key]; + Object.entries(values).forEach(([key, value]) => { if (value === '') { - errors[key] = 'kan ikke være tomt'; + freshErrors[key] = 'kan ikke være tomt'; } else if (key === 'email' && !EmailValidator.validate(value)) { - errors[key] = 'er ikke en gyldig e-post'; + freshErrors[key] = 'er ikke en gyldig e-post'; } else { - delete errors[key]; + delete freshErrors[key]; } }); + setErrors(freshErrors); + setTouched(freshTouched); + }; - this.setState({ errors, touched }); - } + const fieldHasError = (field) => { + return touched.has(field) && field in errors; + }; - fieldHasError(field) { - return this.state.touched.has(field) && field in this.state.errors; - } + const canSubmitForm = () => { + return Object.keys(errors).length === 0; + }; - canSubmitForm() { - return Object.keys(this.state.errors).length === 0; - } + // useEffect(() => { + // if (prevRegisterError !== registerError) { + // setErrors(registerError); + // } + // }, []); - firstNameInput() { + const showFieldError = (field) => { + if (!fieldHasError(field)) { + return null; + } return ( - - + + {errors[field]} + + ); + }; + + const firstNameInput = () => { + return ( + + Fornavn { - this.setState({ firstName }, () => { - this.validateForm('firstName'); - }); + onChangeText={(value) => { + setFirstName(value); + validateForm('firstName'); }} onSubmitEditing={() => { - this.lastNameInputRef._root.focus(); + lastNameInputRef.current.focus(); }} - value={this.state.firstName} + value={firstName} /> - {this.fieldHasError('firstName') && } - + {fieldHasError('firstName') && } + ); - } + }; - lastNameInput() { + const lastNameInput = () => { return ( - - + + Etternavn { - this.lastNameInputRef = ref; - }} + ref={lastNameInputRef} returnKeyType="next" - onChangeText={(lastName) => { - this.setState({ lastName }, () => { - this.validateForm('lastName'); - }); + onChangeText={(value) => { + setLastName(value); + validateForm('lastName'); }} onSubmitEditing={() => { - this.emailInputRef._root.focus(); + emailInputRef.current.focus(); }} - value={this.state.lastName} + value={lastName} /> - {this.fieldHasError('lastName') && } - + {fieldHasError('lastName') && } + ); - } + }; - emailInput() { + const emailInput = () => { return ( - - + + E-post { - this.emailInputRef = ref; - }} + ref={emailInputRef} keyboardType="email-address" autoCapitalize="none" autoCorrect={false} returnKeyType="next" - onChangeText={(email) => { - this.setState({ email }, () => { - this.validateForm('email'); - }); + onChangeText={(value) => { + setEmail(value); + validateForm('email'); }} onSubmitEditing={() => { - this.phoneInputRef._root.focus(); + phoneInputRef.current.focus(); }} - value={this.state.email} + value={email} /> - {this.fieldHasError('email') && } - + {fieldHasError('email') && } + ); - } + }; - phoneNumberInput() { + const phoneNumberInput = () => { return ( - - + + Mobilnummer { - this.phoneInputRef = ref; - }} + ref={phoneInputRef} returnKeyType="next" keyboardType="phone-pad" - onChangeText={(phoneNumber) => { - this.setState({ phoneNumber }, () => { - this.validateForm('phoneNumber'); - }); + onChangeText={(value) => { + setPhoneNumber(value); + validateForm('phoneNumber'); }} onSubmitEditing={() => { - this.passwordInputRef._root.focus(); + passwordInputRef.current.focus(); }} - value={this.state.phoneNumber} + value={phoneNumber} /> - {this.fieldHasError('phoneNumber') && } - + {fieldHasError('phoneNumber') && } + ); - } - - passwordInput() { + }; + const passwordInput = () => { return ( - - + + Passord { - this.passwordInputRef = ref; - }} + ref={passwordInputRef} secureTextEntry={true} autoCapitalize="none" autoCorrect={false} - onChangeText={(password) => { - this.setState({ password }, () => { - this.validateForm('password'); - }); + onChangeText={(value) => { + setPassword(value); + validateForm('password'); }} - onSubmitEditing={this.onRegisterPress} - value={this.state.password} + onSubmitEditing={onRegisterPress} + value={password} /> - {this.fieldHasError('password') && } - + {fieldHasError('password') && } + ); - } - - componentWillReceiveProps(nextProps) { - if (this.props.registerError !== nextProps.registerError) { - this.setState({ errors: nextProps.registerError }); - } - } - - showNonFieldError = () => { - const errors = this.props.registerError; + }; + const showNonFieldError = () => { if (Object.keys(errors).length !== 0 && 'non_field_errors' in errors) { const err = errors.non_field_errors; const errorFormatted = err ? err[0] : 'Kunne ikke registrere bruker, prøv igjen...'; @@ -201,50 +196,8 @@ export default class UserRegister extends Component { return ; }; - showFieldError = (field) => { - if (!this.fieldHasError(field)) { - return null; - } - return ( - - {this.state.errors[field]} - - ); - }; - - showSpinner = () => { - if (!this.props.isRegisteringUser) { - return null; - } - return ; - }; - - render() { - return ( - - -
- {this.firstNameInput()} - {this.showFieldError('firstName')} - {this.lastNameInput()} - {this.showFieldError('lastName')} - {this.emailInput()} - {this.showFieldError('email')} - {this.phoneNumberInput()} - {this.showFieldError('phoneNumber')} - {this.passwordInput()} - {this.showFieldError('password')} - {this.showNonFieldError()} - {this.registerbutton()} - {this.showSpinner()} -
-
-
- ); - } - - onRegisterPress = () => { - if (!this.canSubmitForm()) { + const onSubmit = () => { + if (!canSubmitForm()) { Toast.show({ text: 'Noen av feltene er ikke fylt ut riktig', position: 'bottom', @@ -254,25 +207,41 @@ export default class UserRegister extends Component { return; } - this.props.onRegisterPress( - this.state.firstName, - this.state.lastName, - this.state.email, - this.state.phoneNumber, - this.state.password - ); + onRegisterPress(firstName, lastName, email, phoneNumber, password); }; - registerbutton() { - const isDisabled = this.state.touched.size === 0 || this.props.isRegisteringUser || !this.canSubmitForm(); + const registerbutton = () => { + const isDisabled = touched.size === 0 || isRegisteringUser || !canSubmitForm(); return ( - ); - } -} + }; + + return ( + + + {firstNameInput()} + {showFieldError('firstName')} + {lastNameInput()} + {showFieldError('lastName')} + {emailInput()} + {showFieldError('email')} + {phoneNumberInput()} + {showFieldError('phoneNumber')} + {passwordInput()} + {showFieldError('password')} + {showNonFieldError()} + {registerbutton()} + {isRegisteringUser && } + + + ); +}; +export default UserRegister; + const styles = StyleSheet.create({ container: { flex: 1, diff --git a/src/modules/register/UserRegisterContainer.js b/src/modules/register/UserRegisterContainer.js deleted file mode 100644 index d6a99c4..0000000 --- a/src/modules/register/UserRegisterContainer.js +++ /dev/null @@ -1,47 +0,0 @@ -import React, { Component } from 'react'; -import { connect } from 'react-redux'; - -import UserRegister from './UserRegister'; -import { requestRegisterUser } from '../../api'; - -class UserRegisterContainer extends Component { - constructor(state) { - super(state); - this.state = { - isAuthenticated: false, - }; - } - - componentWillReceiveProps(nextProps) { - if (this.state.isAuthenticated !== nextProps.isAuthenticated) { - if (nextProps.isAuthenticated) { - this.props.onRegister(); - } - } - } - - onRegisterPress = (firstName, lastName, email, phoneNumber, password) => { - this.props.requestRegisterUser(firstName, lastName, email, phoneNumber, password); - }; - - render() { - return ( - - ); - } -} - -function storeToProps(store) { - const errors = store.registerError === null ? {} : store.registerError; - return { - isAuthenticated: store.isAuthenticated, - isRegisteringUser: store.isRegisteringUser, - registerError: errors, - }; -} -export default connect(storeToProps, { requestRegisterUser })(UserRegisterContainer); diff --git a/src/modules/register/useUserRegister.js b/src/modules/register/useUserRegister.js new file mode 100644 index 0000000..137929b --- /dev/null +++ b/src/modules/register/useUserRegister.js @@ -0,0 +1,29 @@ +import { useNavigation } from '@react-navigation/native'; +import { useEffect } from 'react'; +import { useSelector, useDispatch } from 'react-redux'; + +import { usePrevious } from '../../hooks'; +import { requestRegisterUser } from '../../api'; + +const useUserRegister = () => { + const dispatch = useDispatch(); + const navigation = useNavigation(); + const { isAuthenticated, isRegisteringUser, registerError } = useSelector((store) => ({ + isAuthenticated: store.isAuthenticated, + isRegisteringUser: store.isRegisteringUser, + registerError: store.registerError === null ? {} : store.registerError, + })); + + const isAuthenticatedPrev = usePrevious(isAuthenticated); + const onRegisterPress = () => (firstName, lastName, email, phoneNumber, password) => + dispatch(requestRegisterUser(firstName, lastName, email, phoneNumber, password)); + + useEffect(() => { + if (isAuthenticatedPrev !== isAuthenticated && isAuthenticated) { + navigation.goBack(); + } + }, [isAuthenticatedPrev, isAuthenticated]); + + return { onRegisterPress, isRegisteringUser, registerError }; +}; +export default useUserRegister; diff --git a/src/screens/UserRegisterScreen.js b/src/screens/UserRegisterScreen.js deleted file mode 100644 index 3e39f5a..0000000 --- a/src/screens/UserRegisterScreen.js +++ /dev/null @@ -1,13 +0,0 @@ -import React, { Component } from 'react'; -import UserRegisterContainer from '../modules/register/UserRegisterContainer'; - -export default class UserRegisterScreen extends Component { - onRegister = () => { - // This works since UserRegisterScreen is allways navigated to from MembershipScreen - this.props.navigation.goBack(); - }; - - render() { - return ; - } -}