0.1.5 • Published 6 years ago

react-agent v0.1.5

Weekly downloads
16
License
MIT
Repository
github
Last release
6 years ago

React Agent

React Agent is a JavaScript library for your client store, server querying, and database management. It can be included in any React project without conflict with other state management tools or REST APIs.

React Agent is easy to learn.

Here's the basic idea: the client runs 'actions' that are defined on the server-side.

// client.js
run(‘setMessage’, { message: ‘Hello World’ })

// server.js
setMessage: {
    action: ‘INSERT INTO messages(text) VALUES(:message)’
}

These actions can be as powerful as you want -- i.e. CRUD operations, API calls, and authentication. Moreover, clients can subscribe to server-side actions so that they receive live updates.

React Agent includes offline-support to render optimistic updates and then synchronization on reestablished network connection. It also features time travel debugging.

Why use React Agent?

The popular conceptualization of state management stores state in two places: data on the client-side and data on the server-side.

To connect these, front-end and back-end developers usually write a lot of code such as HTTP requests, controllers, and routes. It can get complicated. previous

In contrast, React Agent serves as a communication channel between the client and the server. It abstracts state transfer to make it super easy to interact between the client and server. now

Below is a client-side guide. Here's our full documentation.

Getting Started

This guide is focused on client-side usage of React Agent, although it includes necessary details to know about server-side usage. See React Agent Server for more information about server-side set-up.

Installing

Install the package:

npm install react-agent --save

How to use

First, import React Agent into your highest level React component.

import { Agent } from 'react-agent'

Then, wrap your main component with <Agent> to start React Agent when your app loads.

render(
 <Agent>
   <App />
 </Agent>
 , document.querySelector('#root'))

Optionally, you can 1) set an initial state for React Agent with store={ initialStore }. As we’ll see, the state set with React Agent is accessible from any component. And, 2) log in the console what's happening under the hood by including logger={true}.

const initialStore = {
 first: true,
 second: false,
 third: 'ok'
}

render(
 <Agent store={ initialStore } logger={true}>
   <App />
 </Agent>
 , document.querySelector('#root'))

Let’s get started on the fun part. Import React Agent into a React component.

import { get, set, run, emit, on, unsubscribe } from 'react-agent'

There's six methods that make sense to learn. The first two are set and get, which manipulate state on the client-side, but don't interact with the server. The last four are run, emit, on, and unsubscribe, which are used for exchanging client and server-side state. To start, let’s use set to write to the React Agent store and get to return the values.

set and get

The set method takes a property/value pair as its parameters by comma seperation or as an object.

set('username', 'Billy')
set({ username: 'Billy' })

Multiple property/values pairs can be set by including them in consecutive order.

set('age', 28, 'active', true)
set({ age: 28, active: true })

The get method takes a property and returns the associated value.

get(‘username’) // returns ‘Billy’

It is also possible to manipulate client-side state in a more complex way using set and get in conjunction. For example, let's say we want to add a new value to an array in React Agent's store. The array is stored as the value of the property allUsers.

allUsers = get('allUsers')
set('allUsers', [...allUsers, { user: Billy }])

First, we use get to assign the current value of allUsers to a variable. Then, we take advantage of the ES6 spread operator ... to easily add { user: Billy } to allUsers.

Since React Agent’s methods can be imported into any component, React Agent's store is now accessible from any component without ‘passing-down’ props. Under the hood, React Agent uses React’s virtual DOM for efficient rendering.

Note: while React Agent can be used as a store for state, it can also be used without conflict alongside other state management tools such as Redux or React component state.

run

Now, let's examine the four methods that communicate with the server. Since these methods interact with the server, but do not affect React Agent's store, they are often used in conjunction with get and set to update client state.

run can perform any action on the server-side. For example, it might execute a CRUD operation on a SQL database, or it might execute an API call.

run takes a key as its first argument, which corresponds to a matching key on the server-side. When a client calls run on a key, the server executes the action labeled by the matching key.

As its optional second argument, run takes an object to pass to the server's action.

run('addUser', { user: Billy })

Here, we run the action addUser, which executes the action addUser on the server-side. That's all we need to do to add a user!

After the action is completed on the server, the promise returned by run either resolves or rejects. Then, the client can handle returned data, or catch an error.

run('getAllUsers')
  .then(data => {
    set('allUsers', data.users)
  })
  .catch(err => {
    console.log(err)
  })

emit, on, and unsubscribe

In addition to run, three other methods interact with the server: emit, on, and unsubscribe.

emit sends a state update to all clients who have subscribed to a key. Optionally, it takes an object as a second argument to pass to the server.

emit('updateMessages', { cookieID: 937985713 })

on subscribes a client to a key. That is, if emit is called with the corresponding key, the server pushes state updates to all subscribed clients.

on('updateMessages', data => {
  set('allMessages', data.messages)
})

unsubscribe removes a client's subscription to a key so that they no longer receive state updates.

unsubscribe('updateMessages')

Now, let's bring it together in one big example.

// The server will push any updates of 'getAllStudents' to the client.
on('getAllStudents', data => {
  set('allStudents', data.students)
})

// If a user adds Billy as a student, we optimistically update the client's store.
currentUsers = get('allStudents')
set('allStudents', [...currentStudents, { name: Billy }])

// Run the action 'addStudent' to update the server's database.
// If successful, emit an action to all subscribers of 'getAllStudents.'
// If error, revert the client's state to former value before optimistic update.
run('addStudent', { name: Billy })
  .then(() => {
    emit('getAllStudents')
  })
  .catch( err => {
    set('addStudents', currentUsers)
  })

Additional Methods and Features

Time Travel Debugging

React Agent uses Redux under the hood for time travel debugging. To enable this feature, pass devTools={true} to the <Agent> wrapper. Then, use Redux DevTools Chrome extension to travel through time.

render( 
 <Agent devTools={true}>
   <App />
 </Agent>
, document.querySelector('#root'))

destroy

destroy is used to delete a property and its values from React Agent's store. You can pass in multiple properties to delete.

destroy('messages')
destroy('users', 'comments', 'messages')

getStore

getStore returns an object containing the current state of React Agent's entire store. Alternatively, call get with no arguments for the same result.

currentState = getStore()
currentState = get()

isOfflineCacheEmpty

isOfflineCacheEmpty returns a boolean indicating whether any actions sent to the server have not yet been sent back as a response to the client. This method can be useful to determine whether the client has unsaved changes. For example, say the network connection drops, but a user continues interacting with the site because of optimistic rendering. If isOfflineCacheEmpty is then called, it would return false.

isOfflineCacheEmpty() // returns true or false

In fact, React Agent can alert a user that they have unsaved changes -- this feature is turned-off by default. If a user tries to navigate away from the site, it provides a pop-up warning. It uses isOfflineCacheEmpty under the hood. To turn on this feature, pass offlinePopUp={true} to the <Agent> wrapper.

render(
 <Agent offlinePopUp={true}>
   <App />
 </Agent>
 , document.querySelector('#root'))

run

run also accepts multiple keys as arguments in the form of an array. As its optional second argument, it takes an object which is passed to every action included in the array. In this configuration, run returns a promise, which resolves to an object containing the key of each action and its respective response from the server.

run(['addUser', 'addMessage'], { user: 'Billy', message: 'trapped in a simulation.' })
// returns { addUser: { id: 2956739 }, addMessage: { time: 2018-01-19T01:10:47 }}

Contributors

Authors

License

This project is licensed under the MIT License - see the LICENSE.txt file for details.

0.1.5

6 years ago

0.1.4

6 years ago

0.1.3

6 years ago

0.1.2

6 years ago

0.1.1

6 years ago

0.0.67

6 years ago

0.0.66

6 years ago

0.0.61

6 years ago

0.0.6

6 years ago

0.0.5

6 years ago

0.0.4

6 years ago

0.0.2

6 years ago

0.0.1

6 years ago

1.0.1

6 years ago

1.0.0

6 years ago