1.0.33 • Published 6 years ago

rxa v1.0.33

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

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

1.0.33

6 years ago

1.0.31

6 years ago

1.0.30

6 years ago

1.0.29

6 years ago

1.0.28

6 years ago

1.0.27

6 years ago

1.0.26

6 years ago

1.0.25

6 years ago

1.0.24

6 years ago

1.0.23

6 years ago

1.0.22

6 years ago

1.0.20

6 years ago

1.0.19

6 years ago

1.0.18

6 years ago

1.0.17

6 years ago

1.0.16

6 years ago

1.0.15

6 years ago

1.0.14

6 years ago

1.0.13

6 years ago

1.0.12

6 years ago

1.0.11

6 years ago

1.0.10

6 years ago

1.0.9

6 years ago

1.0.7

6 years ago

1.0.6

6 years ago

1.0.5

6 years ago

1.0.4

6 years ago

1.0.3

6 years ago

1.0.2

6 years ago

1.0.1

6 years ago

1.0.0

6 years ago