This content originally appeared on DEV Community and was authored by Nikolaos Bampaliaris
Hello!
I was using Angular for like 3 years and recently I decided to switch to React, mostly because you have a lot more freedom to do things your way. The problem that I'm facing now is how to manage my code, I just end up having ugly components with a lot of code and JSX. For example (also I'm not sure how to split useCallback functions to different files):
import React from "react";
import styles from './RegisterForm.module.css';
import * as MuiMat from '@mui/material';
import * as MuiIcons from '@mui/icons-material';
import GlobalContext from "../../../context/global-context";
import { AccountModel } from "../../../models/account.model";
interface RegisterFormI
{
onFormSubmit(account: AccountModel): void
}
interface PasswordStateI
{
pass : string
passValid : boolean
passError : string
rePass : string
rePassValid : boolean
rePassError : string
passMatch : boolean
}
const RegisterForm: React.FC<RegisterFormI> = (props)=>
{
const globalCTX = React.useContext(GlobalContext);
const [username, setUsername] = React.useState<string>('');
const [usernameError, setUsernameError] = React.useState<string>('');
const [usernameValid, setUsernameValid] = React.useState<boolean>(true);
const [email, setEmail] = React.useState<string>('');
const [emailError, setEmailError] = React.useState<string>('');
const [emailValid, setEmailValid] = React.useState<boolean>(true);
const [pass, setPass] = React.useState<PasswordStateI>({
pass: '', passValid: true, passError: '',
rePass: '', rePassValid: true, rePassError: '',
passMatch: true
});
//Reused in single state forms.
const handlerFunctionality = React.useCallback(
(value: string, setField: any, setFieldValid: any, setFieldError: any)=>
{
setField(value);
if (value.trim().length === 0)
{
setFieldValid(false);
setFieldError(globalCTX.locale.required);
}
else
{
setFieldValid(true);
}
}, [globalCTX]);
//Username Handler (Single state)
const onUsernameHandler = React.useCallback( (obj)=>
{
let v = obj.target.value as string;
handlerFunctionality(v, setUsername, setUsernameValid, setUsernameError);
}, [handlerFunctionality]);
//Email Handler (Single state)
const onEmailHandler = React.useCallback( (obj)=>
{
let v = obj.target.value as string;
handlerFunctionality(v, setEmail, setEmailValid, setEmailError);
}, [handlerFunctionality]);
//Pass Handler (Multiple states in one object)
const onPassHandler = React.useCallback( (obj)=>
{
let v = obj.target.value as string;
if (v.trim().length === 0)
{
setPass( (prevState: PasswordStateI): PasswordStateI=>
{
let match = pass.rePass === v;
return {...prevState, pass: v, passValid: false, passError: globalCTX.locale.required, passMatch: match};
});
}
else
{
setPass( (prevState: PasswordStateI): PasswordStateI=>
{
let match = pass.rePass === v;
return {...prevState, pass: v, passValid: true, passMatch: match};
});
}
}, [globalCTX, pass]);
//RePass Handler (Multiple states in one object)
const onRePassHandler = React.useCallback( (obj)=>
{
let v = obj.target.value as string;
if (v.trim().length === 0)
{
setPass( (prevState: PasswordStateI): PasswordStateI=>
{
let match = pass.pass === v;
return {...prevState, rePass: v, rePassValid: false, rePassError: globalCTX.locale.required, passMatch: match};
});
}
else
{
setPass( (prevState: PasswordStateI): PasswordStateI=>
{
let match = pass.pass === v;
return {...prevState, rePass: v, rePassValid: true, passMatch: match};
});
}
}, [globalCTX, pass]);
//Check form validity as a whole.
const checkFormValidity = React.useCallback((): boolean=>
{
let valid = true;
if (username.trim().length === 0)
{
setUsernameValid(false);
setUsernameError(globalCTX.locale.required);
valid = false;
}
if (email.trim().length === 0)
{
setEmailValid(false);
setEmailError(globalCTX.locale.required);
valid = false;
}
if (pass.pass.trim().length === 0)
{
setPass( (prevPass: PasswordStateI):PasswordStateI=>
{
return {...prevPass, passValid: false, passError: globalCTX.locale.required}
});
valid = false;
}
if (pass.rePass.trim().length === 0)
{
setPass( (prevPass: PasswordStateI):PasswordStateI=>
{
return {...prevPass, rePassValid: false, rePassError: globalCTX.locale.required}
});
valid = false;
}
return valid;
}, [username, email, pass, globalCTX]);
//Submit Form Functionality.
const {onFormSubmit} = props;
const onSubmit = React.useCallback(()=>
{
let account: AccountModel = new AccountModel();
if ( !checkFormValidity() ) return;
account.m_username = username;
account.m_email = email;
account.m_password = pass.pass;
onFormSubmit(account);
}, [username, email, pass, onFormSubmit, checkFormValidity]);
//Rendering.
const margins = '1rem';
return (
<React.Fragment>
<form className={styles.registerForm}
>
<div className={styles.registerTitle}>
<label className={styles.registerTitleLabel}>
{globalCTX.locale.register}
</label>
</div>
<MuiMat.TextField
style={{marginTop: margins, marginBottom: margins}}
onChange={onUsernameHandler}
value={username}
fullWidth
required
label={globalCTX.locale.username}
placeholder={globalCTX.locale.usernameHint}
InputProps={{startAdornment:(
<MuiMat.InputAdornment position="start">
<MuiIcons.AccountCircle />
</MuiMat.InputAdornment>
)}}
error={!usernameValid}
helperText={!usernameValid ? usernameError : ''}
/>
<MuiMat.TextField
style={{marginTop: margins, marginBottom: margins}}
fullWidth
required
value={email}
onChange={onEmailHandler}
label={globalCTX.locale.email}
type="email"
placeholder={globalCTX.locale.emailHint}
InputProps={{startAdornment:(
<MuiMat.InputAdornment position="start">
<MuiIcons.AlternateEmail />
</MuiMat.InputAdornment>
)}}
error={!emailValid}
helperText={!emailValid ? emailError : ''}
/>
<MuiMat.TextField
style={{marginTop: margins, marginBottom: margins}}
fullWidth
value={pass.pass}
onChange={onPassHandler}
label={globalCTX.locale.password}
type="password"
placeholder={globalCTX.locale.passwordHint}
InputProps={{startAdornment:(
<MuiMat.InputAdornment position="start">
<MuiIcons.Key />
</MuiMat.InputAdornment>
)}}
error={!pass.passValid}
helperText={!pass.passValid ? pass.passError : ''}
/>
<MuiMat.TextField
style={{marginTop: margins, marginBottom: margins}}
fullWidth
value={pass.rePass}
onChange={onRePassHandler}
label={globalCTX.locale.re_password}
type="password"
placeholder={globalCTX.locale.re_passwordHint}
InputProps={{startAdornment:(
<MuiMat.InputAdornment position="start">
<MuiIcons.LockReset />
</MuiMat.InputAdornment>
)}}
error={!pass.rePassValid || !pass.passMatch}
helperText={!pass.rePassValid ? pass.rePassError : '' || !pass.passMatch ? globalCTX.locale.invalidPassMatch : ''}
/>
<div className={styles.registerButton}>
<MuiMat.Button
variant="contained"
startIcon={<MuiIcons.Login />}
onClick={onSubmit}
disabled={!usernameValid || !pass.passValid || !emailValid || !pass.rePassValid}
>
{globalCTX.locale.register}
</MuiMat.Button>
</div>
</form>
</React.Fragment>
);
};
export default RegisterForm;
Any suggestions? Thanks. Other suggestions about my code (for example state management) are welcome as well.
This content originally appeared on DEV Community and was authored by Nikolaos Bampaliaris
Nikolaos Bampaliaris | Sciencx (2022-03-30T14:39:13+00:00) New to react. Any suggestions for code management and maintainability?. Retrieved from https://www.scien.cx/2022/03/30/new-to-react-any-suggestions-for-code-management-and-maintainability/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.