cubiz v0.4.1
cubiz
Installation
npm
npm i cubiz --save
yarn
yarn add cubiz
Features
- Simple API
- Easy to mainternant
- Async cancellation supported
- Fully Typescript supported
Concepts
- The Cubiz is where to store the data of the application. One cubiz contains one kind of data and handle all business logic that relates to that data.
- The effect is where to describes how we can interact with the cubiz. When a effect called, if the effect contains async code, the cubiz loading status becomes true. After the effect is done, if no more running effect, the cubiz loading status becomes false, no matter the effect is sucess or fail.
- The Provider is where to handle cubiz repository, the repository stores all cubiz instances. When cubiz uses another cubiz instance, it calls the repository for resolving that
Usages
Basic Usages
import { useCubiz } from "cubiz";
// define a cubiz with initial state is 1
const CounterCubiz = ({ state }) => state(1);
// update cubiz state
const IncrementAction = ({ state }) => state((prev) => prev + 1);
const App = () => {
// retrieve cubiz object and destruct state, call props
const { state, call } = useCubiz(CounterCubiz);
// call an action
const increment = () => call(IncrementAction);
return <button onClick={increment}>Count: {state}</button>;
};
Advanced Usages
Sharing effect with other cubiz
function Counter1Cubiz({ state }) {
state(1);
}
function Counter2Cubiz({ state }) {
state(2);
}
function increment({ state }) {
state.value++;
}
const counter1 = useCubiz(Counter1Cubiz);
const counter2 = useCubiz(Counter1Cubiz);
// both cubizes can call same effect
counter1.call(increment);
counter2.call(increment);
Using other cubiz instances
function SettingsCubiz({ state }) {
// load settings from somewhere
const settings = JSON.parse(localStorage.getItem("settings"));
state(settings);
}
function ThemeCubiz({ state, use }) {
// use() function returns instance of the cubiz from its initFn
const settings = use(SettingsCubiz);
state(settings.state.theme);
}
Understanding cubiz key
The cubiz is created from the key and initFn, the key is null by default. So we can have multiple cubizes that has same initFn but they have different keys. This is useful when you want to sperate data of the cubiz but still want to keep its logic.
async function ArticleCubiz({ key }) {
// assume that the key is article id
const articleId = key;
const article = await call(loadArticleById, articleId);
state(article);
}
const article1 = useCubiz(ArticleCubiz, { key: 1 });
const article2 = useCubiz(ArticleCubiz, { key: 2 });
console.log(article1 !== article2);
// dont need to create ArticleCache to cache all loaded articles
// mutating article1 does not impact article2 and its connected components
The cubiz repository uses strict comparison (===) to identify cubiz key, but you can use array as the key and the repo is smart enough to do comparison for each array item
// in javascript, two arrays are difference
console.log([1, 2, 3] === [1, 2, 3]);
// but you use array for cubiz key
// let say we have ProductionListCubiz that contains product list fetching logic
function ProductionListCubiz({ key }) {
// the key contains category and orderBy
const [category, orderBy] = key;
}
const list1 = useCubiz(ProductionListCubiz, { key: ["food", "name"] });
const list2 = useCubiz(ProductionListCubiz, { key: ["food", "name"] });
const list3 = useCubiz(ProductionListCubiz, { key: ["food", "date"] });
const list4 = useCubiz(ProductionListCubiz, { key: ["gadget", "date"] });
console.log(list1 === list2); // true
console.log(list2 === list3); // false
Mutating state
Probaly, we can use method state(prev => ...) to mutate state, cubiz provides a lot of mutations you can use for object, array, value etc.
import { mutate, push } from "cubiz";
function addTodo({ state, call }, title) {
// using state
state((todos) => todos.concat([{ title }]));
// using mutation
call(mutate, push({ title }));
}
Mutating array
import { mutate, removeAll } from "cubiz";
function removeTodo({ state, call }, id) {
state((todos) => todos.filter((x) => x.id !== id)); // in case of no todo found, the state is still created
call(
mutate,
removeAll((x) => x.id === id),
// mutate item that matches predicate
item((x) => x.id === id, prop("done", toggle())),
// mutate item at specified position
item(1, prop("title", "new title")),
item("first", prop("title", "new title")),
item("last", prop("title", "new title"))
// mutate all items
item('all', prop("title", "new title"))
); // the state will keep it as is if no todo found
}
Mutating nested props
import { mutate } from "cubiz";
function UserCubiz({ state, call }) {
// initial state
state({
id: 1,
name: "admin",
roles: [],
articles: [],
work: {
company: {
address: {
street: "",
city: "",
},
},
},
});
const old = state.value;
state({
...old,
name: "myname",
roles: [...old.roles, "admin", "user", "superadmin"],
articles: [...old.articles, { title: "abc" }],
work: {
...old.work,
company: {
...old.company,
address: {
...old.company.address,
street: "abc",
},
},
},
});
// using mutate effect
call(
mutate,
set("name", "myname"),
prop("roles", push("admin", "user", "superadmin")),
prop("articles", push({ title: "abc" })),
prop("work", prop("compary", prop("address", set("street", "abc"))))
);
}
API References
Please refer this link for futher information https://linq2js.github.io/cubiz/
Live examples
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago