Learn more about our current job openings and benefits of working at FSL.
Detailed reviews and feedback from past and current clients.
Get to know the Management Team behind FullStack Labs.
Our step-by-step process for designing and developing new applications.
Writings from our team on technology, design, and business.
Get answers to the questions most frequently asked by new clients.
Learn about our company culture and defining principles.
A high level overview of FullStack Labs, who we are, and what we do.
A JavaScript framework that allows rapid development of native Android and IOS apps.
A JavaScript framework maintained by Facebook that's ideal for building complex, modern user interfaces within single page web apps.
A server side programming language known for its ease of use and speed of development.
A lightweight and efficient backend javascript framework for web apps.
An interpreted high-level programming language great for general purpose programming.
A JavaScript framework maintained by Google that addresses many of the challenges encountered when building single-page apps.
A JavaScript framework that allows developers to build large, complex, scalable single-page web applications.
A progressive JavaScript framework known for its approachability, versatility, and performance.
A progressive JavaScript framework known for its approachability, versatility, and performance.
A progressive JavaScript framework known for its approachability, versatility, and performance.
A progressive JavaScript framework known for its approachability, versatility, and performance.
A progressive JavaScript framework known for its approachability, versatility, and performance.
A progressive JavaScript framework known for its approachability, versatility, and performance.
A progressive JavaScript framework known for its approachability, versatility, and performance.
View a sampling of our work implemented using a variety of our favorite technologies.
View examples of the process we use to build custom software solutions for our clients.
View projects implemented using this javascript framework ideal for building complex, modern user interfaces within single page web apps.
View projects implemented using this framework that allows rapid development of native Android and IOS apps.
View projects implemented using this backend javascript framework for web apps.
View projects implemented using this high-level programming language great for general purpose programming.
View projects implemented using this server side programming language known for its ease of use and speed of development.
We have vast experience crafting healthcare software development solutions, including UI/UX Design, Application Development, Legacy Healthcare Systems, and Team Augmentation. Our development services help the healthcare industry by enhancing accessibility, productivity, portability, and scalability.
We offer a range of custom software development solutions for education companies of all sizes. We're experts in Education Software Development and specialists in enhancing the learning experience across web, mobile, and conversational UI.
We're experts in developing Custom Software Solutions for the Logistics Industry. Our work offered a whole new and more efficient way for Logistics companies to manage their crucial operations.
We partner with various construction industry organizations to build custom software development solutions. Our Construction Software Development Services allow construction companies to manage projects, resources, and documentation.
We have vast experience crafting healthcare software development solutions, including UI/UX Design, Application Development, Legacy Healthcare Systems, and Team Augmentation. Our development services help the healthcare industry by enhancing accessibility, productivity, portability, and scalability.
We offer a range of custom software development solutions for education companies of all sizes. We're experts in Education Software Development and specialists in enhancing the learning experience across web, mobile, and conversational UI.
We're experts in developing Custom Software Solutions for the Logistics Industry. Our work offered a whole new and more efficient way for Logistics companies to manage their crucial operations.
We partner with various construction industry organizations to build custom software development solutions. Our Construction Software Development Services allow construction companies to manage projects, resources, and documentation.
Learn more about our current job openings and benefits of working at FSL.
Detailed reviews and feedback from past and current clients.
Get to know the Management Team behind FullStack Labs.
Our step-by-step process for designing and developing new applications.
Writings from our team on technology, design, and business.
Get answers to the questions most frequently asked by new clients.
Learn about our company culture and defining principles.
A high level overview of FullStack Labs, who we are, and what we do.
A JavaScript framework that allows rapid development of native Android and IOS apps.
A JavaScript framework maintained by Facebook that's ideal for building complex, modern user interfaces within single page web apps.
A server side programming language known for its ease of use and speed of development.
A lightweight and efficient backend javascript framework for web apps.
An interpreted high-level programming language great for general purpose programming.
A JavaScript framework maintained by Google that addresses many of the challenges encountered when building single-page apps.
A JavaScript framework that allows developers to build large, complex, scalable single-page web applications.
A progressive JavaScript framework known for its approachability, versatility, and performance.
A dynamic programming language used in all sorts of web and mobile applications.
A cross-platform programming language designed to run robust applications on any device.
A UI toolkit used to build natively compiled applications from a single codebase.
A functional programming language that’s ideal for scalability, maintainability, and reliability.
A Customer Relationship Management (CRM) platform that seamlessly integrates with your business operations.
A high-performance programming language that makes it easy to build simple, reliable, and efficient software.
View a sampling of our work implemented using a variety of our favorite technologies.
View examples of the process we use to build custom software solutions for our clients.
View projects implemented using this javascript framework ideal for building complex, modern user interfaces within single page web apps.
View projects implemented using this framework that allows rapid development of native Android and IOS apps.
View projects implemented using this backend javascript framework for web apps.
View projects implemented using this high-level programming language great for general purpose programming.
View projects implemented using this server side programming language known for its ease of use and speed of development.
In the previous article, we set up the Ruby on Rails API. Now, we are ready to set up our React Native app and implement a state management system. For this tutorial, we will use the 0.60.5 version of React Native and Redux.
Note: Don’t forget to keep the Ruby on Rails API running in a separate terminal tab so you can test your connection throughout the tutorial.
The process for setting up your React Native app will vary depending on your computer’s operating system and the platform you choose for rendering the app.
First, run cd .. to go to the project’s root directory. Then, go to React Native’s Getting Started guide. Click on the React Native CLI Quickstart tab, and follow the instructions. Make sure you are viewing instructions for the OS (MacOS, Windows, or Linux) and platform (Android or iOS) combination you will be using to render the app.
When you arrive at the Creating a new application section, do not install the most recent version of React Native. Instead, install the 0.60.5 version using this command:
-- CODE language-jsx keep-markup --
react-nativeinitnoteApp--versionreact-native@0.60.5
Continue following the steps in the React Native guide until you see the Welcome Screen on your emulator or device.
Redux manages app-wide state in a single store object that is passed to specific components, usually called connected components. The data passed in from the store object is then passed down to lower level components as props from connected components. Actions, with ActionTypes, are dispatched to Reducers that respond by updating the state of the app. To learn more about Redux, take a look at the Redux docs.
We also need to install redux-thunk, a middleware that will allow us to make asynchronous requests in our actions.
Open package.json and add the following libraries to the dependencies section:
-- CODE language-jsx keep-markup --
"dependencies": {
"react": "16.8.6",
"react-native": "0.60.5",
"react-redux": "^6.0.0",
"redux": "^4.0.1",
"redux-thunk": "^2.3.0"
},
Run npm i or yarn to install these new dependencies. Add these libraries to the app by updating App.js as follows:
-- CODE language-jsx keep-markup --
import React from 'react';
import { View } from 'react-native';
import thunk from 'redux-thunk';
import { Provider } from 'react-redux';
import { applyMiddleware, combineReducers, createStore } from 'redux';
import reducers from './app/reducers';
const App = () => {
return (
<view> </view>
);
};
export default App;
We will use the combineReducers function to combine all app reducers into a single reducer, called rootReducer.
-- CODE language-jsx keep-markup --
const rootReducer = combineReducers({...reducers});
Next, we will create a store using the createStore function. This function will take the rootReducer and applyMiddleware functions as parameters. To set it up, pass thunk into applyMiddleware.
-- CODE language-jsx keep-markup --
const store = createStore(rootReducer, applyMiddleware(thunk));
Finally, pass the store object into the <provider></provider> component and wrap the <view> </view>in this component
-- CODE language-jsx keep-markup --
import React from 'react';
import {View} from 'react-native';
import thunk from 'redux-thunk';
import {Provider} from 'react-redux';
import {applyMiddleware, combineReducers, createStore} from 'redux';
import reducers from './app/reducers';
const rootReducer = combineReducers({...reducers});
const store = createStore(rootReducer, applyMiddleware(thunk));
const App = () => {
return (
<provider store="{store}"></provider>
<view></view>
);
};
exportdefault App;
A typical redux folder structure separates actions, actionTypes, and reducers into separate folders. This project will follow a similar structure.
-- CODE language-jsx keep-markup --
app/
actions/
noteActions.js
actionTypes/
notes.js
reducers/
index.js
notes.js
Create the files referenced above with your editor, or use the following command:
-- CODE language-jsx keep-markup --
$ mkdir -p app/actions/ app/actionTypes/ app/reducers/
$ touch app/actions/noteActions.js app/actionTypes/notes.js app/reducers/index.js app/reducers/notes.js
Let’s take a look at the app/actionTypes/notes.js file to declare our action types. Our app needs to perform two primary actions: fetching and creating notes. Each action requires three different states to represent the status of the request: loading, success, and failure. Therefore, we need to create a total of six actionTypes. In the app/actionTypes/notes.js file, create the corresponding actionTypes.
-- CODE language-jsx keep-markup --
exportconst FETCH_NOTES = 'FETCH_NOTES';
exportconst FETCH_NOTES_SUCCESS = 'FETCH_NOTES_SUCCESS';
exportconst FETCH_NOTES_FAILURE = 'FETCH_NOTES_FAILURE';
exportconst CREATE_NOTE = 'CREATE_NOTE';
exportconst CREATE_NOTE_SUCCESS = 'CREATE_NOTE_SUCCESS';
exportconst CREATE_NOTE_FAILURE = 'CREATE_NOTE_FAILURE';
Now, we need to create the actions that will fire these actionTypes. Open app/actions/notesActions.js and import the actionTypes we defined above.
-- CODE language-jsx keep-markup --
import * as types from '../actionTypes/notes';
To create the action fetchNotes() and dispatch the FETCH_NOTES actionType, add the following to the app/actions/notesActions.js file:
-- CODE language-jsx keep-markup --
exportfunctionfetchNotes() {
returnasync dispatch => {
dispatch({type: types.FETCH_NOTES});
};
}
Then, use the fetch function to call the notes endpoint on the Rails API. If the response is successful, use the .json() function to convert the content to JSON. If the response is not successful, throw an error.
-- CODE language-jsx keep-markup --
exportfunctionfetchNotes() {
returnasync dispatch => {
dispatch({type: types.FETCH_NOTES});
let response = await fetch('http://localhost:5000/notes');
if (response.status !== 200) {
thrownew Error('FETCH_ERROR');
}
response = await response.json();
dispatch({type: types.FETCH_NOTES_SUCCESS, data: response});
};
};
Wrap the request in a try/catch block to capture any failures, and dispatch the FETCH_NOTES_FAILURE actionType when a failure is detected.
-- CODE language-jsx keep-markup --
exportfunctionfetchNotes() {
returnasync dispatch => {
dispatch({type: types.FETCH_NOTES});
try {
let response = await fetch('http://localhost:5000/notes');
if (response.status !== 200) {
thrownew Error('FETCH_ERROR');
}
response = await response.json();
dispatch({type: types.FETCH_NOTES_SUCCESS, data: response});
} catch (error) {
dispatch({type: types.FETCH_NOTES_FAILURE, error});
}
};
}
With the fetch action complete, we can now implement the createNote action. Add the following to the app/actions/notesActions.js file:
-- CODE language-jsx keep-markup --
exportfunctioncreateNote(note) {
returnasync dispatch => {
dispatch({type: types.CREATE_NOTE});
try {
let response = await fetch('http://localhost:5000/notes', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({note}),
});
if (response.status !== 200) {
thrownew Error('FETCH_ERROR');
}
response = await response.json();
dispatch({type: types.CREATE_NOTE_SUCCESS, data: response});
} catch (error) {
dispatch({type: types.CREATE_NOTE_FAILURE, error});
}
};
}
The only difference between the createNote action and the fetchNotes action is the fetch configuration because we need to send the note data that we intend to create. The fetch HTTP method should be changed to POST and the body property should contain the note data, converted to a JSON string.
-- CODE language-jsx keep-markup --
let response = await fetch('http://localhost:5000/notes', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({note}),
});
Reducers require an initial state that defines all values that will be used into the store. Open app/reducers/notes.js and create a simple object:
-- CODE language-jsx keep-markup --
const INITIAL_STATE = {
data: [],
status: null,
error: null,
createStatus: null,
createError: null,
};
The data property stores the notes we get from the fetchNotes action. The status and error properties handle the different states of the fetchNotes request. Finally, the createStatus and createError handle the statuses of the createNote request.
Below the INITIAL_STATE object, create a basic reducer function:
-- CODE language-jsx keep-markup --
const INITIAL_STATE = {
data: [],
status: null,
error: null,
createStatus: null,
createError: null,
};
exportdefault (state = INITIAL_STATE, action) => {
switch (action.type) {
default:
return state;
}
};
The parameter action passes in the action data and type returned from a dispatched action. Let's create the first case for the fetchNotes action:
-- CODE language-jsx keep-markup --
exportdefault (state = INITIAL_STATE, action) => {
switch (action.type) {
case 'FETCH_NOTES':
return {
...state,
status: 'loading',
error: null,
};
default:
return state;
}
};
Each case returns the full app state, which means we need to destructure the current state along with new properties to preserve the full state. Next, create the remaining cases for the fetchNotes action:
-- CODE language-jsx keep-markup --
exportdefault (state = INITIAL_STATE, action) => {
switch (action.type) {
case 'FETCH_NOTES':
return {
...state,
status: 'loading',
error: null,
};
case 'FETCH_NOTES_SUCCESS':
return {
...state,
status: 'success',
data: action.data,
error: null,
};
case 'FETCH_NOTES_FAILURE':
return {
...state,
status: 'failure',
error: action.error,
};
default:
return state;
}
};
FETCH_NOTES is dispatched before our fetch call to the API and ther and sets loading to true so we can display the loading state in the UI.
FETCH_NOTES_SUCCESS is dispatched on success and adds the returned notes to the store.
FETCH_NOTES_FAILURE is dispatched when the action fails and sets the error property to the error returned.
Next, create the createNote cases:
-- CODE language-jsx keep-markup --
switch (action.type) {
...
case 'CREATE_NOTE':
return {
...state,
createStatus: 'loading',
createError: null,
};
case 'CREATE_NOTE_SUCCESS':
return {
...state,
createStatus: 'success',
data: [...state.data, action.data],
createError: null,
};
case 'CREATE_NOTE_FAILURE':
return {
...state,
createStatus: 'failure',
createError: action.error,
};
...
}
The initial and failure case are similar to the corresponding fetchNotes cases. The CREATE_NOTE_SUCCESS case, however, appends the newly created note to the end of the list of notes. This saves us from making another fetchNotes call to refresh the list of notes with the new note:
-- CODE language-jsx keep-markup --
data: [...state.data, action.data],
Finally add our reducer to the index file, app/reducers/index.js:
-- CODE language-jsx keep-markup --
import notes from './notes';
exportdefault {
notes,
};
We have now created a React Native app, set up Redux, created actions, and created a reducer. In the final article of this series, we build the UI and connect it with Redux.
Check out the Github repo for this tutorial to see the completed app.
---
At FullStack Labs, we pride ourselves on our ability to push the capabilities of cutting-edge frameworks like React. Interested in learning more about speeding up development time on your next project? Contact us.
We’d love to learn more about your project.
Engagements start at $75,000.