React Native Experiment: CRUD with Realm + Tcomb Form Validation


INTRODUCTION

This is an experimental app from scratch to test CRUD with Realm Platform + Tcomb Form Validation in React Native. The purpose of this article is for documentation and to share to other developers, especially beginners on how to create apps with basic CRUD operations with realm platform and how to validate user inputs in short time.


REPOSITORY

This is not a step-by-step guide. So better check the repo. :)


TOOLS AND PACKAGES

This experimental app is created from scratch with react-native init. Following npm packages were utilized:


THE EXPERIMENTAL APP — My Employees Record

The app contains only two (2) screens.

  1. The Employee List Screen with Flatlist
  2. Employee Information Form
Screen 1

CRUD with Realm

Firstly, we need to define the schema of our data.

//Schema
const EmployeeSchema = {
name: 'Employee',
primaryKey: 'key',
properties: {
key: 'string', //primary key
firstname: 'string',
middlename: 'string',
lastname: 'string',
nickname: 'string',
birthday: {type: 'date'},
gender: 'string',
address: 'string',
position: 'string',
salary: {type: 'double'},
}
};

Next, we will create functions to perform CRUD operations

componentDidMount() {
this._initData();
}
_initData = async() => {
await Realm.open({schema: [EmployeeSchema], schemaVersion: 4})
.then(realm => {
this.setState({ realm})
})
.catch(error => {
console.log(error);
});
  this._getData()
}
//Realm READ
_getData = () => {
const oEmployeeList = this.state.realm.objects('Employee').sorted('lastname');
this.setState({ _aEmployeeList: [...oEmployeeList] })
}
//Realm CREATE, UPDATE, DELETE
_writeToStore = async (oData, bDelelete = false) => {
try{
const bUpdateFlag = false;
const realm = this.state.realm;
const iKey = '';
//Delete Key
if(bDelelete){
iKey=oData.key;
bUpdateFlag = true;
}
//Add Key
else if(this.state._oActiveEmployee.key === ''){
iKey = String(this.state._aEmployeeList.length);
}
//Modify Key
else{
iKey = String(this.state._oActiveEmployee.key);
bUpdateFlag = true;
}

await realm.write(() => {
let oEmployee = realm.create('Employee', {
key: iKey,
firstname: oData.firstname || '',
middlename: oData.middlename || '',
lastname: oData.lastname || '',
nickname: oData.nickname || '',
birthday: utils.convertDateToString(oData.birthday) || '',
gender: oData.gender || '',
address: oData.address || '',
position: oData.position || '',
salary: oData.salary || '',
}, bUpdateFlag);
//Delete Action
if(bDelelete){
realm.delete(oEmployee);
}
});
this._getData();
return true;
}

Tcomb Form Validation

Set-up Tcomb From and its properties

render(){
const GENDER = t.enums(GENDER_OPTIONS)
const POSITION = t.enums(POSITION_OPTIONS)
const OPTIONS = {
fields: {
firstname:{
label: 'FIRST NAME' ,
returnKeyType: 'next',
autoCorrect: false,
onSubmitEditing: (event) => {this.refs.form_employee.getComponent('middlename').refs.input.focus()},
error: ERROR_MESSAGE
},
middlename:{
label: 'MIDDLE NAME' ,
returnKeyType: 'next',
onSubmitEditing: (event) => {this.refs.form_employee.getComponent('lastname').refs.input.focus()},
error: ERROR_MESSAGE
},
lastname:{
label: 'LAST NAME' ,
returnKeyType: 'next',
onSubmitEditing: (event) => {this.refs.form_employee.getComponent('nickname').refs.input.focus()},
error: ERROR_MESSAGE
},
nickname:{
label: 'NICKNAME' ,
returnKeyType: 'next',
onSubmitEditing: (event) => {this.refs.form_employee.getComponent('nickname').refs.input.focus()},
error: ERROR_MESSAGE
},
birthday:{
label: 'BIRTHDAY',
mode:'date',
maximumDate: new Date(),
config:{
format: (strDate) => utils.convertDateToString(strDate, 'YYYY-MM-DD')
},
error: ERROR_MESSAGE
},
gender:{
template: CustomSelectPickerTemplate,
label: 'GENDER',
error: ERROR_MESSAGE
},
address:{
label: 'ADDRESS' ,
returnKeyType: 'done',
error: ERROR_MESSAGE
},
position:{
template: CustomSelectPickerTemplate,
prompt: 'Select Position',
label: 'POSITION',
error: ERROR_MESSAGE
},
salary:{
label: 'RATE PER MONTH (USD)' ,
returnKeyType: 'done',
error: ERROR_MESSAGE
}
},
stylesheet: stylesheet
}
const EMPLOYEE = t.struct({
firstname: t.String,
middlename: t.String,
lastname: t.String,
nickname: t.maybe(t.String),
birthday: t.Date,
gender: GENDER,
address: t.String,
position: POSITION,
salary: t.Number
})
return(
<FormContainer
onSubmit = {this._onSubmit}
onCancel = {this._onCancel}
padding = {35}
title={this.props.title}>
<Form 
ref='form_employee'
type={EMPLOYEE}
onChange={this._onChange}
value={this.state._oEmployee}
options={OPTIONS}/>

</FormContainer>
)
}

NOTES FROM THE AUTHOR

This is just an experimental app. However, this can be used as a template to create apps with basic CRUD features. You may leave a feedback. :)