@keystack/rentrato-js-sdk v0.1.1
Rentrato JS SDK
Mission
This SDK is intended to provide authentication, communication and UI components necessary to integrate the RentratoUI and RentratoApi into new or existing applications.
Rentrato JS SDK intends to acheive these goals:
Create standalone and composable UI components that can be easily integrated into new and existing web and mobile projects with little effort.
Provide API communication services so that any application can retreive Agent, User, Lead, Listing and Apartment data from the Rentrato Platform
Keystack/rentrato-api
. (https://www.github.com/Keystack/rentrato-api)
Provide simple FLUX state management tooling to shorten learning curve by providing domain specific Higher Order Components for composability and action dispatch simplicity.
Provide an array of styles/themes templates to easily change how components are displayed.
What is included?
- API Authentication Services / Utilities
- Domain Specific hoc's
- Generic & Domain Specific Flux State Management Tooling
- Domain specific, observable and immutable Data Stores
- Domain specific action creators
- Async Middleware baked-in
- Rentrato UI Components
Installation
Note: This package will be privately available once completed via npm and can be inluded in your project by running :
npm install @keystack/rentrato-sdk-js
You can choose to use the existing state management system or use one of your own.
Documentation Server
A documentation server has been provided and will contain UI component usage examples. It can be loaded and served locally by running:
npm start
Server is located at http://localhost:3001
Rentrato State Management
Domain Specific Data Stores
The RentratoJS includes data stores that store and normalize data retrieved from the Rentrato API.
Each data store is responsible for updating and emitting changes of it's own state in response to actions fired from the corresponding action creator.
AppStore
maintains state of application/views - (Used in all Rentrato Applications)
UserStore
maintains state for all user data - (Used in RentratoLive, RentratoList, RentratoUI)
ApartmentsStore
maintains state for all apartment data - (User in RentratoLive)
AgentsStore
maintains state for all agent data - (Used in RentratoConnect)
ListingsStore
maintains state for all listing data - (Used in RentratoConnect)
ToursStore
maintains state for all tour data - (Used in RentratoConnect)
LeadStore
maintains state for all lead data - (User in Rentrato Connect)
Unlike most FLUX applications, these stores are not singletons (for info about this see here). Instances can be created using the provided helper function like so:
import createAgentStore from 'stores/agents';
...
const optionalInitialState = {};
const store = createAgentStore(optionalInitialState);
Using and instanciating the stores directly (not recommended) would require attaching change listeners within React.Component lifecycle hooks like so:
import React, { PureComponent } from 'react'
...
import createStore from 'stores/agents';
const store = createStore();
export default class ComponentWithAgentStore extends PureComponent {
handleChange=()=>{
// update your components state
}
componentDidMount=()=>{
store.onChange(this.handleChange)
}
componentDidUnmount=()=>{
store.offChange(this.handleChange)
}
}
Note: Using stores this way is not recommended, however should you choose to, we'd recommend creating custom hoc's to attach stores and pass data via props. For an example of how to do that, checkout our implementation here.
Higher Order Components
We've provided a collection of Higher Order Components that act as Providers
for each of our data stores. They can be used like so:
import React, { PureComponent } from 'react'
default class CustomComponent extends PureComponent {
render(){
const { agent } = this.props
return(
<div className="agent-name">
{agent.full_name}
</div>
)
}
}
export withAgent(CustomComponent);
If your project supports ES7 decorators, then you could also do:
import React, { PureComponent } from 'react';
import { withAgent } from 'rentrato-js-sdk';
@withAgent
export default class CustomComponent extends PureComponent {
render(){
const { agent } = this.props
return(
<div className="agent-name">
{agent.full_name}
</div>
)
}
}
Domain Specific Action Creators
In order to interact and change the state of your stores we've provided a few action creators.
AppActions
- updates view and app level state (source)
UserActions
- updates user state (source)
AgentActions
- updates agent state (source)
ApartmentsActions
- updates apartments state (source)
LeadsActions
- updates lead state (source)
ListingsActions
- updates listings state (source)
ToursActions
- updates tour state (source)
These action creators not only update your local state but send updates to the API asynchronously. Once data is returned from the Api they notify the respective store of the change so it may update it's state;
They can be used like so:
import { signUp, signIn, fetch } from 'actions/user';
export default class Login extends PureComponent{
onLoginSubmit=(evt)=>{
const { email, password } = this.props
// Dispatch "USER_LOGIN"
// action on form submit
signIn({
email,
password
});
}
render(){
...
// attach onLoginSubmit
// to login button
}
}
Rentrato UI Components
Flux Implementation
RentratoJS SDK uses a FLUX pattern for state management. It's comprised of the three pillars of most FLUX applications: Dispatcher (singleton), Action Creators, Data Stores. If you aren't familiar with FLUX, we suggest you do some reading as it is out scope of this doc.
The key differences in our implentation from classic FLUX are:
- Data stores are not singletons as with most FLUX apps
- Singleton data stores make it next to impossible for server rendering
Instead, each of our store classes return functions that can be used as so:
import createStore from 'stores/apartments';
// initialState is optional
const initialState = {};
const store = createStore( initialState );
Here, createStore()
returns an instance of ApartmentsStore
loaded with an initial state and any data that may have been cached from within it's respective domain.
Note: These store instances are immutable and cannot/should not be mutated directly. They should only be updated by action dispatches that they care about.
getState() : returns a shallow copy of the current state
getStateClone() : returns a deep copy of the current state
persist(@object) : backs up current state in local storage and merges @object
onChange(@cb) : attaches a callback to be fired when change is observed
offChange(@cb) : removes callback (typically used in React.Component.cdum lifecycle hook)
Note: These methods are considered low-level and we recommend only using these when creating new HOC's or avoid using all together and use it's respective HOC.
- Action creators provide Async (thunk) middleware out of the box.
In order to provide a fully implemented FLUX implementation we baked in Promise-based async functionality into our Action Creators. To dispatch an action, just use one of it's instance methods and it will dispatch the corresponding action on your behalf.
Action Dispatch Example:
Here, the siginIn