Skip to content

linq2js/rxa

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

33 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

RXA

An lib to create an application which is based on React + Redux + Rxjs + Ramda + Reselect. It supports developer to build React app faster.

Cool features:

  1. Support auto prefetch components
  2. Support lazy module loading, dynamic actions
  3. No reducer needed
  4. Support async redux action
  5. Simple action dispatching
  6. Auto applying reselect to improve app rendering performance
  7. Auto load/save app state using localStorage

Examples:

  1. Hello world
  2. Prefetchable component
  3. Auto load/save app state
  4. Todo list
  5. $async usage
  6. Free drawing component
  7. Dots game
  8. Huge Form (200 inputs)
  9. Form and react-select

Hello world

codesandbox.io

import React from "react";
import { render } from "react-dom";
import { create } from "rxa";

// create app with intial state
const app = create({ name: "World" })
  // register hello action
  .action("hello", (name, postfix) => alert(`Hello ${name}${postfix}`));

// create connection
const helloButtonConnect = app.connect(
  // properties mapper, it receives 3 arguments state, actions, ownProps
  ({ name }, { hello }) => ({
    name,
    hello
  })
);

const HelloButton = helloButtonConnect(({ name, hello }) => (
  <button onClick={() => hello(name, " !!!")}>Click me</button>
));

render(
  <app.Provider>
    <HelloButton />
  </app.Provider>,
  document.getElementById("root") || document.body
);

Prefetchable component

codesandbox.io

import React from "react";
import { render } from "react-dom";
import { create } from "rxa";

// create app with intial state
const app = create({ user: "linq2js" }).action(
  "updateUser:user", // state prop
  x => x.toLowerCase()
);

const userInfoConnect = app.connect(
  // extract user from store
  ({ user }) => ({ user }),
  // pass user to fetching action
  ({ user }) => user,
  // extract user from props and pass it to fetching action
  user => fetch(`https://api.github.com/users/${user}`).then(x => x.json())
);

// create user info component
const UserInfo = userInfoConnect(({ $fetch }) => (
  <div>
    <pre>
      {$fetch.error
        ? JSON.stringify($fetch.error)
        : $fetch.loading
          ? "Fetching user data"
          : JSON.stringify($fetch.payload, null, 4)}
    </pre>
    {$fetch.payload && (
      <a href={$fetch.payload.html_url} target="_blank">
        <img src={$fetch.payload.avatar_url} width={200} alt="User Avatar" />
      </a>
    )}
  </div>
));

const userInputConnect = app.connect(
  // extract user from store and updateUser from action collection
  ({ user }, { updateUser }) => ({ user, updateUser })
);

// create user input  component
const UserInput = userInputConnect(({ user, updateUser }) => (
  <input type="text" onChange={e => updateUser(e.target.value)} value={user} />
));

render(
  <app.Provider>
    <div>
      <UserInput />
      <UserInfo />
    </div>
  </app.Provider>,
  document.getElementById("root") || document.body
);

Auto load/save app state

codesandbox.io

import React from "react";
import { render } from "react-dom";
import { create } from "rxa";

// create app with intial state
const app = create("appState", { counter: 0 })
  // register hello action
  .action("updateCounter:counter", () => ({ $current }) =>
    $current() + 1
  );

// create connection
const counterConnect = app.connect(
  // properties mapper, it retrieves 3 arguments state, actions, ownProps
  ({ counter }, { updateCounter }) => ({
    counter,
    updateCounter
  })
);

const Counter = counterConnect(({ counter, updateCounter }) => (
  <button onClick={updateCounter}>Counter: {counter}</button>
));

render(
  <app.Provider>
    <Counter />
  </app.Provider>,
  document.getElementById("root") || document.body
);

API References:

  1. create
  2. app.action
  3. app.actions
  4. app.autoSave
  5. app.connect
  6. app.debounce
  7. app.dispatch
  8. app.getState
  9. app.invoke
  10. app.Provider
  11. app.reducer
  12. app.selector
  13. app.subscribe

create

create(initialState: object): app
Create new application with initial state

create(localStorageKey: string, defaultState: object): app
Create new application and load state from localStorage with give key. If nothing loaded, defaultState will be used

app.action

app.action(statePropAndActionName: string, action: function): app
Register new action. Action result will update to given state property name automatically. Supports object property path

app.action(stateProp: string, action: function, actionName: string): app
Register new action with specified actionName. Action result will update to given state property name automatically. Supports object property path

app.action(stateProp: string, action: function, options: ActionOptions): app
Register new action with specified options. Action result will update to given state property name automatically. Supports object property path. Available options:

  • single: bool For async action only. Action only executes once at the same time. The previous execution will be stopped if there is new execution.
  • dispatchStatus For async action only. Will dispatch executing status of this action when it is changed (loading, success, fail...).
    app.connect((state, actions) => {
       const { submitAsync } = actions;
       console.log(submitAsync.status);
       console.log(submitAsync.loading);
       console.log(submitAsync.success);
       console.log(submitAsync.fail);
    });

Instead of returning a partial state object directly, an action can return a function that takes action collection. Action collection contains margin actions ($state, $current, $done, $fail, $success)

app.action('test', () => ( actions ) => {
   const { $state, $current, $done, $fail, $success, $async } = actions;
   
   $state(); // get current state
   $current(); // get current state prop value
   $done(() => alert('done')); // execute callback once current action done
   $success(() => alert('success')); // execute callback once current action success
   $fail(() => alert('fail')); // execute callback once current action fail
   
   return fetch(url);
});

For $async magic action, see <a href="https://codesandbox.io/s/8klzr8q558">$async usage</a>

app.actions

app.actions(actionModel: object): app
Register multiple actions at once

    app.actions({
        username: x => x, // change user
        password: x => x, // change password
        __: [x => x, { single: true, name: 'submit' }], // register action with an options
        account: { // can register new action under specified action group/namespace
            create: x => x
        }
    });

app.autoSave

app.autoSave(): app
Enable auto save with default options

app.autoSave(localStorageKey: string): app
Enable auto save with specified localStorageKey

app.autoSave(options: object): app
Enable auto save with an options. Available options:

  • key: string localStorage key to be used for saving app state
  • debounce: number specific debounce time to delay saving

app.connect

app.connect(propsMapper: (state, actions) => object): ReduxConnection
Create Redux Connection with specified propsMapper

app.connect(propsMapper: (state, actions) => object, prefetch: () => Promise: ReduxConnection
Create Redux Connection with specified propsMapper and specific prefetch action.

app.connect(propsMapper: (state, actions) => object, prefetchArgsSelector: (props) => prefetchArgs, prefetch: prefetchArgs => Promise): ReduxConnection
Create Redux Connection with specified propsMapper and specific prefetch action. prefetchArgsSelector will be called to select args for prefetch action

See Prefetchable component for usage.

app.debounce

app.debounce(func: function, delay: number)
Create debounced function wrapper with specified delay time

app.dispatch

app.dispatch(action): app
Call redux store.dispatch(action)

app.getState

app.getState(): state
Call redux store.getState()

app.invoke

app.Provider
Return binded Redux Provider

app.reducer

app.reducer(reducer: function)

Register redux reducer for special purpose

app.selector

app.selector(...args): Selector
Call reselect.createSelector(...args)

app.subscribe

app.subscribe(state => any): Subscription
Adds a change listener. It will be called any time an action is dispatched, and some part of the state tree may potentially have changed

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published