0.1.1 • Published 5 years ago

@keystack/rentrato-js-sdk v0.1.1

Weekly downloads
-
License
ISC
Repository
github
Last release
5 years ago

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:

  1. Create standalone and composable UI components that can be easily integrated into new and existing web and mobile projects with little effort.

  2. 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)

  1. Provide simple FLUX state management tooling to shorten learning curve by providing domain specific Higher Order Components for composability and action dispatch simplicity.

  2. Provide an array of styles/themes templates to easily change how components are displayed.

What is included?

  1. API Authentication Services / Utilities
  2. Domain Specific hoc's
  3. Generic & Domain Specific Flux State Management Tooling
    • Domain specific, observable and immutable Data Stores
    • Domain specific action creators
    • Async Middleware baked-in
  4. 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:

  1. 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.

  1. 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