reaxn
v0.0.14
Published
Hooks for managing, dispatching, caching async actions
Downloads
12
Maintainers
Readme
reaxn
Installation
Using npm
npm i reaxn --save
Using yarn
yarn add reaxn
Usages
Counter App
import React from "react";
import { render } from "react-dom";
import { createController, useAction, Provider } from "reaxn";
const controller = createController({
state: { count: 1 },
});
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
const GetCount = ({ store, invalidate }) => {
// GetCount action will be invalidated whenever store.count changed
invalidate("store.count");
return store.count;
};
const GetDoubleCount = ({ call }) => {
const count = call("count", GetCount);
return count * 2;
};
const IncreaseCount = ({ store }) => {
// when store.count changed, the controller will emit store.count event
store.count++;
};
const IncreaseCountAsync = async ({ call }) => {
// delay in 1s
await delay(1000);
// then call IncreaseCount action
call(IncreaseCount);
};
const App = () => {
// call GetCount and retrieve its result
const [{ result: count }] = useAction("count", GetCount);
const [{ result: doubleCount }] = useAction("doubleCount", GetDoubleCount);
// with lazy = true, no action called, just return action invoker
const [, increase] = useAction({ action: IncreaseCount, lazy: true });
// retrieve loading status when action is invoking
const [{ loading }, increaseAsync] = useAction({
action: IncreaseCountAsync,
lazy: true,
});
return (
<>
<h1>Count: {count}</h1>
<h1>Count x 2: {doubleCount}</h1>
<button onClick={() => increase()}>Increase</button>
<button onClick={() => increaseAsync()} disabled={loading}>
{loading ? "Increasing...." : "Increase Async"}
</button>
</>
);
};
render(
<Provider controller={controller}>
<App />
</Provider>,
document.getElementById("root")
);
User Management App
import React, { useRef } from "react";
import { render } from "react-dom";
import { createController, useAction, Provider } from "reaxn";
const controller = createController({});
// get all users, no invalidate condition
const GetUsers = () => {
return fetch("https://jsonplaceholder.typicode.com/users").then((x) =>
x.json()
);
};
const AddUser = ({ update }, user) => {
user = {
...user,
id: Math.floor(Math.random() * 10000),
};
fetch({
url: "https://jsonplaceholder.typicode.com/users",
method: "POST",
body: JSON.stringify(user),
headers: {
"Content-type": "application/json; charset=UTF-8",
},
});
// perform optimistic update
update("users", GetUsers, (users) =>
// insert new user at the beginning of the list
[user].concat(users)
);
};
const App = () => {
const [{ result: users, loading }] = useAction("users", GetUsers);
const [, addUser] = useAction({ action: AddUser, lazy: true });
const nameRef = useRef();
const usernameRef = useRef();
const emailRef = useRef();
const handleSubmit = (e) => {
e.preventDefault();
addUser({
name: nameRef.current.value,
username: usernameRef.current.value,
email: emailRef.current.value,
});
// clear inputs
nameRef.current.value = "";
usernameRef.current.value = "";
emailRef.current.value = "";
nameRef.current.focus();
};
return (
<>
<form onSubmit={handleSubmit}>
<h2>Add New User</h2>
<input ref={nameRef} placeholder="Name" />
<br />
<input ref={usernameRef} placeholder="Username" />
<br />
<input ref={emailRef} placeholder="Email" />
<br />
<button type="submit">Submit</button>
</form>
<xmp>
{loading
? "Loading all users..."
: JSON.stringify(
users.map(({ id, name, username, email }) => ({
id,
name,
username,
email,
})),
null,
2
)}
</xmp>
</>
);
};
render(
<Provider controller={controller}>
<App />
</Provider>,
document.getElementById("root")
);