Gathering detailed insights and metrics for resy
Gathering detailed insights and metrics for resy
npm install resy
Typescript
Module System
Min. Node Version
Node Version
NPM Version
TypeScript (99.66%)
JavaScript (0.12%)
CSS (0.12%)
HTML (0.11%)
Total Downloads
20,251
Last Day
14
Last Week
65
Last Month
379
Last Year
6,973
12 Stars
1,017 Commits
1 Forks
1 Watching
4 Branches
1 Contributors
Minified
Minified + Gzipped
Latest Version
11.0.3
Package Id
resy@11.0.3
Unpacked Size
188.66 kB
Size
49.14 kB
File Count
15
NPM Version
10.7.0
Node Version
18.20.4
Publised On
14 Oct 2024
Cumulative downloads
Total Downloads
Last day
-6.7%
14
Compared to previous day
Last week
-13.3%
65
Compared to previous week
Last month
241.4%
379
Compared to previous month
Last year
9.9%
6,973
Compared to previous year
1
1
34
1npm i resy 2 3# yarn add resy 4# pnpm add resy
1import { createStore, useStore, ComponentWithStore } from "resy"; 2 3const store = createStore({ count: 0 }); 4 5// for hook component 6function App() { 7 const { count } = useStore(store); // or store.useStore(); 8 return ( 9 <> 10 {count} 11 <button onClick={() => store.count++}>increase</button> 12 </> 13 ); 14} 15 16// for class component 17class AppClass extends ComponentWithStore { 18 19 store = this.connectStore(store); 20 21 render() { 22 const { count } = this.store; 23 return ( 24 <> 25 {count} 26 <button onClick={() => { store.count++; }}>increase</button> 27 </> 28 ); 29 } 30}
resy requires the version of React v >= 16.8
API | Description |
---|---|
createStore | Create a store container for state |
useStore | Use state from the store container generated by createStore |
setState | Update data |
syncUpdate | Synchronously update data |
1const demoStore1 = createStore({ 2 count: 0, 3 text: "hello", 4});
1type DemoStateType = { count: number; text?: number | string }; 2// In this way, the type of text can be 3// more accurately identified as number or string or undefined 4const demoStore2 = createStore<DemoStateType>({ 5 count: 0, 6});
1// This is a very important feature for retrieving the latest time or other data. 2const demoStore3 = createStore(() => { 3 return { 4 count: 0, 5 time: Date.now(), 6 }; 7});
1const demoStore4 = createStore({ 2 count: 0, 3 increase() { 4 // this point store object, as follows example 5 // The updates and usage of these APIs will be detailed in subsequent chapters 6 this.count++; 7 // this.setState({ count: this.count + 1 }); 8 // this.restore(); 9 10 // demoStore4.count++; 11 // demoStore4.setState({ count: demoStore3.count + 1 }); 12 }, 13});
1import { createStore } from "resy"; 2 3type StateType = { 4 count: number; 5 text: string; 6 info: { name: string }; 7 ageList: { age: number }[]; 8 increase(): void; 9 inputValue?: string; 10}; 11 12// The generated store can be shared globally 13const store = createStore<StateType>({ 14 count: 0, 15 text: "hello", 16 info: { name: "Jack" }, 17 ageList: [{age: 12}, { age: 16 }], 18 increase() { 19 this.count++; 20 }, 21});
1// Store such as login and theme can set unmountRestore to false 2// so that it will not be reset globally. 3const userStore = createStore<{ userName: string; userId: number }>( 4 { 5 userName: "wenmu", 6 userId: 0, 7 }, 8 { 9 unmountRestore: false, 10 }, 11); 12const themeStore = createStore<{ themeStyle: "dark" | "light" }>( 13 { 14 themeStyle: "dark", 15 }, 16 { 17 unmountRestore: false, 18 }, 19);
1import { useStore } from "resy"; 2 3function App() { 4 const { count, text } = useStore(store); 5 // or 6 // const { count, text } = store.useStore(); 7 8 return ( 9 <> 10 <p>{count}</p> 11 <p>{text}</p> 12 </> 13 ); 14}
1import { useStore } from "resy"; 2 3function App() { 4 const { userName } = userStore.useStore(); 5 const { themeStyle } = themeStore.useStore(); 6 7 return ( 8 <> 9 <p>{userName}</p> 10 <p>{themeStyle}</p> 11 <button onClick={() => { userStore.userName = "LF" }}>nameChange</button> 12 <button onClick={() => { themeStore.setState({ themeStyle: "light" }) }}>themeChange</button> 13 </> 14 ); 15}
1import { useStore } from "resy"; 2 3function App() { 4 const state = store.useStore(); 5 6 return ( 7 <> 8 <p>{state.count}</p> 9 <p>{state.text}</p> 10 </> 11 ); 12}
1import { useStore } from "resy"; 2 3function App() { 4 const { 5 count, text, 6 // The use of these api will be described in detail later. 7 setState, syncUpdate, restore, subscribe, 8 } = store.useStore(); 9 10 return ( 11 <> 12 <p>{count}</p> 13 <p>{text}</p> 14 </> 15 ); 16}
1import { useStore } from "resy"; 2 3function App() { 4 const { count, text } = store.useStore(); 5 6 // Updates can be assigned directly 7 function btn2() { 8 store.count++; 9 store.text = "456asd"; 10 } 11 12 return ( 13 <> 14 <p>{count}</p> 15 <p>{text}</p> 16 </> 17 ); 18}
1import { ComponentWithStore, PureComponentWithStore } from "resy"; 2 3/** 4 * @description ComponentWithStore is inherited from React Component, 5 * PureComponentWithStore is inherited from React PureComponent; 6 */ 7class AppClass extends ComponentWithStore { 8 9 store = this.connectStore(store); 10 11 render() { 12 const { count } = this.store; 13 return ( 14 <> 15 {count} 16 <button onClick={() => { store.count++; }}>button +</button> 17 </> 18 ); 19 } 20} 21 22class PureAppClass extends PureComponentWithStore { 23 store = this.connectStore(store); 24 25 render() { 26 const { count } = this.store; 27 return ( 28 <> 29 {count} 30 <button onClick={() => { store.count++; }}>button +</button> 31 </> 32 ); 33 } 34}
1import { ComponentWithStore, createStore } from "resy"; 2 3/** 4 * @description The update methods of internal "this.userStore" and "this.themeStore" 5 * are the same as those of the connected store itself, and can be called directly. 6 */ 7class AppClass extends ComponentWithStore { 8 9 userStore = this.connectStore(userStore); 10 11 themeStore = this.connectStore(themeStore); 12 13 render() { 14 const { userName } = this.userStore; 15 const { theme } = this.themeStore; 16 return ( 17 <> 18 <span>{userName}</span> 19 <span>{theme}</span> 20 <button onClick={() => { userStore.userName = "LD" }}> 21 nameChange 22 </button> 23 <button onClick={() => { themeStore.setState({ theme: "light" }) }}> 24 themeChange 25 </button> 26 </> 27 ); 28 } 29}
1import { useStore } from "resy"; 2 3function App() { 4 const { 5 info: { name }, ageList, inputValue, 6 } = store.useStore(); 7 8 function btn2() { 9 // store.info.name = "Jack"; // Invalid update 10 // store.ageList[0] = { age: 7 }; // Invalid update 11 12 store.info = { name: "Jack" }; // Effective update 13 store.ageList = [{age: 7}]; // Effective update 14 } 15 16 return ( 17 <> 18 <p>{name}</p> 19 {ageList.map(item => `Age:${item}`)}<br/> 20 <button onClick={btn2}>btn2</button> 21 </> 22 ); 23}
1import { createStore } from "resy"; 2 3const store = createStore({ 4 count: 0, 5 text: "ok", 6 getTextPro(str?: number | string) { 7 /** 8 * @description Here, using `useStore` works fine even in class components, 9 * as we have made it compatible. 10 * In fact, if it's needed only in class components, 11 * you can directly use `this` to achieve the purpose of referencing data internally within the function for rendering. 12 * 🌟 The reason for using `this.useStore()` within `getTextPro` is because, 13 * in the demo below, the `App` component doesn't reference the `text` data within `store.useStore()`. 14 * Therefore, when updating the `text` state, if `useStore` isn't called inside `getTextPro`, 15 * it won't be possible to track the reference to the data for updates. Of course, 16 * this example is specific to hook components. As mentioned earlier, 17 * in class components, `this.useStore()` isn't actually necessary; you could directly use `this`. 18 * However, the usage of `this.useStore()` within `getTextPro` remains compatible even if `getTextPro` is placed inside a class component. 19 */ 20 const { text } = this.useStore(); 21 // Returns the final result for rendering. 22 return `${str ?? ""}_${text}_world`; 23 }, 24}); 25 26const App = () => { 27 const { count, getTextPro } = store.useStore(); 28 29 return ( 30 <div> 31 <div>count:{count}</div> 32 <div>textPro:{getTextPro("none")}</div> 33 <button 34 onClick={() => { 35 store.count++; 36 }} 37 > 38 countChange 39 </button> 40 <button 41 onClick={() => { 42 store.text = "hello"; 43 }} 44 > 45 textChange 46 </button> 47 </div> 48 ); 49}; 50
1import { createStore, ComponentWithStore } from "resy"; 2 3class App extends ComponentWithStore { 4 store = this.connectStore(store); 5 6 render() { 7 const { count, getTextPro } = this.store; 8 return ( 9 <div> 10 <div>count:{count}</div> 11 <div>textPro:{getTextPro("none")}</div> 12 <button onClick={() => store.count++}> 13 countChange 14 </button> 15 <button onClick={() => store.text = "hello"}> 16 textChange 17 </button> 18 </div> 19 ); 20 } 21}
1import { useStore } from "resy"; 2 3function App() { 4 const { count, text } = store.useStore(); 5 6 return ( 7 <> 8 <div>{count}</div> 9 <div>{text}</div> 10 <button 11 onClick={() => { 12 store.setState({ 13 text: "demo-setState", 14 count: count + 1, 15 }); 16 }} 17 > 18 btn 19 </button> 20 </> 21 ); 22}
1import { useStore } from "resy"; 2 3function App() { 4 const { text } = store.useStore(); 5 6 return ( 7 <button 8 onClick={() => { 9 store.setState({ 10 text: "cur-text", 11 }, nextState => { 12 console.log(nextState.text === "cur-text"); // true 13 }); 14 }} 15 > 16 {text} 17 </button> 18 ); 19}
the difference between the callback of setState and the callback of this.setState of class components
1import { Component } from "react"; 2 3class TestClassX extends Component { 4 constructor() { 5 super(); 6 this.state = { count: 0, text: "class-x" }; 7 } 8 9 render() { 10 const { count, text } = this.state; 11 return ( 12 <> 13 {count},{text} 14 <button 15 onClick={() => { 16 this.setState({ 17 text: "Try", 18 }, () => { 19 console.log(this.state.count === 9); // true 20 }); 21 this.setState({ count: 9 }); 22 }} 23 > 24 btn 25 </button> 26 </> 27 ); 28 } 29}
1import { useStore, createStore } from "resy"; 2 3const store = createStore({count: 0, text: "hello"}); 4 5function App() { 6 const { text } = store.useStore(); 7 8 return ( 9 <button 10 onClick={() => { 11 store.setState({ 12 text: "cur-text", 13 }, nextState => { 14 console.log(nextState.text === "cur-text"); // true 15 console.log(nextState.count === 0); // true 16 console.log(store.count === 9); // true 17 }); 18 store.setState({count: 9}); 19 }} 20 > 21 {text} 22 </button> 23 ); 24}
1import { useStore } from "resy"; 2 3const store = createStore({count: 0, text: "hello"}); 4 5function App() { 6 const { count, text } = store.useStore(); 7 8 function btnClick1() { 9 store.setState(() => { 10 // Returns the object that will eventually be updated 11 // through the calculation of complex business logic 12 return { 13 count: count + 1, 14 text: "B-Way-setState-with-function", 15 }; 16 }); 17 } 18 19 function btnClick2() { 20 store.count = 9; 21 // The prevState parameter of the function 22 store.setState(prevState => { 23 console.log(prevState.count === 9); // true 24 console.log(store.count === 9); // true 25 return { 26 text: "ok", 27 }; 28 }); 29 } 30 31 return ( 32 <> 33 <div>{count}</div> 34 <div>{text}</div> 35 <button onClick={btnClick1}>btn-1</button> 36 <button onClick={btnClick2}>btn-2</button> 37 </> 38 ); 39}
1import { useStore, syncUpdate } from "resy"; 2 3/** 4 * @description 🌟 The main purpose of syncUpdate is to solve the problem 5 * that input box updates such as input cannot be updated in an asynchronous environment. 6 */ 7function App() { 8 const { inputValue } = store.useStore(); 9 10 function inputChange(event: React.ChangeEvent<HTMLInputElement>) { 11 store.syncUpdate({ 12 inputValue: event.target.value, 13 }); 14 // @example B 15 // store.syncUpdate(prevState => { 16 // // prevState is same as setState's prevState. 17 // return { 18 // inputValue: event.target.value, 19 // }; 20 // }); 21 // @example C 22 // You can also use the callback function 23 // store.syncUpdate({ 24 // inputValue: event.target.value, 25 // }, nextState => { 26 // console.log(nextState); 27 // }); 28 } 29 30 return ( 31 <input value={inputValue} onChange={inputChange}/> 32 ); 33}
1import { useStore } from "resy"; 2 3// Updates to count data will not cause Text components to re-render 4function Text() { 5 const { text } = store.useStore(); 6 return <p>{text}</p>; 7} 8 9// Updates to text data will not cause Count components to re-render 10function Count() { 11 const { count } = store.useStore(); 12 return <p>{count}</p>; 13} 14 15function App() { 16 const { increase, name } = store.useStore(); 17 18 return ( 19 <> 20 <Text/> 21 <Count/> 22 <div>{name}</div> 23 <button onClick={() => { store.name = "app"; }}>btn-name</button> 24 <button onClick={increase}>btn+</button> 25 <button onClick={() => { store.count-- }}>btn-</button> 26 </> 27 ); 28}
1import { useStore, ComponentWithStore } from "resy"; 2 3// Updates to count data will not cause Text components to re-render 4class TextClass extends ComponentWithStore { 5 6 store = this.connectStore(store); 7 8 render() { 9 const { text } = this.store; 10 return ( 11 <p>{text}</p> 12 ); 13 } 14} 15 16// Updates to text data will not cause Count components to re-render 17class CountClass extends ComponentWithStore { 18 19 store = this.connectStore(store); 20 21 render() { 22 const { count } = this.store; 23 return ( 24 <p>{count}</p> 25 ); 26 } 27} 28 29class AppClass extends ComponentWithStore { 30 31 store = this.connectStore(store); 32 33 render() { 34 const { increase, name } = this.store; 35 return ( 36 <> 37 <Text/> 38 <Count/> 39 <div>{name}</div> 40 <button onClick={() => { store.name = "app" }}>btn-name</button> 41 <button onClick={increase}>btn+</button> 42 <button onClick={() => { store.count-- }}>btn-</button> 43 </> 44 ); 45 } 46}
API | Description |
---|---|
useConciseState | Concise version of useState |
subscribe | Subscribe for changes in store data generated by createStore |
useSubscription | Hook of subscribe |
restore | Restore data of store, with re-render effect |
setOptions | Set the options parameter of createStore |
The functionality of useConciseState is not limited to just a concise syntax on the surface. Its deeper capability is to deconstruct the store and provide sub-components with a doorway that allows for comprehensive control over the store's data, rendering, updates, and subscriptions.
1import { useConciseState } from "resy"; 2 3const initialState = { 4 count: 123, 5 text: "hello-consice", 6}; 7 8function App() { 9 const { count, text, store, setState } = useConciseState(initialState); 10 11 return ( 12 <> 13 <div 14 onClick={() => { 15 setState({ 16 count: count + 1, 17 text: "ASD", 18 }); 19 // or 20 // store.count++; 21 // store.text = "ASD"; 22 // or 23 // store.setState({ 24 // count: count + 1, 25 // text: "ASD", 26 // }); 27 // store has all the data of useConciseState 28 // and the restore, syncUpdate, and subscribe methods 29 }} 30 > 31 {count} 32 </div> 33 <div>{text}</div> 34 </> 35 ); 36}
restore、syncUpdate、subscribe these api can also be deconstructed and used directly.
1import { useEffect } from "react"; 2import { useConciseState } from "resy"; 3 4function App() { 5 const { count, text, restore, syncUpdate, subscribe } = useConciseState(initialState); 6 7 useEffect(() => { 8 return subscribe(({ effectState }) => { 9 console.log(effectState); 10 }, ["text"]); 11 }, []); 12 13 return ( 14 <> 15 <input 16 value={text} 17 onChange={(event: React.ChangeEvent<HTMLInputElement>) => { 18 syncUpdate({text: event.target.value}); 19 }} 20 /> 21 <div onClick={() => restore()}>reset-btn</div> 22 <div>{text}</div> 23 </> 24 ); 25}
1import { useConciseState, ConciseStoreHeart } from "resy"; 2 3type State = { 4 count: number; 5 text: string; 6}; 7 8function ChildOne(props: ConciseStoreHeart<State>) { 9 const { store } = props; 10 const { count, text } = useStore(store); 11 12 return ( 13 <> 14 <p>ChildOne-count:{count}</p> 15 <p>ChildOne-text:{text}</p> 16 <button 17 onClick={() => { 18 store.setState({ 19 count: 999, 20 text: "ChildOneSetStateNewText", 21 }); 22 }} 23 > 24 childOneBtn 25 </button> 26 </> 27 ); 28} 29 30function ChildTwo(props: ConciseStoreHeart<State>) { 31 const { store } = props; 32 const [data, setData] = useState({ count: 0, text: "hello" }); 33 34 store.useSubscription(({ nextState }) => { 35 setData(nextState); 36 }); 37 38 return ( 39 <> 40 <p>ChildTwo-count:{data.count}</p> 41 <p>ChildTwo-text:{data.text}</p> 42 </> 43 ); 44} 45 46const App = () => { 47 const { count, text, store } = useConciseState<State>({ 48 count: 0, 49 text: "hello", 50 }); 51 52 return ( 53 <> 54 <p>{count}</p> 55 <p>{text}</p> 56 <ChildOne store={store} /> 57 <ChildTwo store={store} /> 58 <button onClick={() => { 59 store.setState({ 60 count: 1, 61 text: "world", 62 }); 63 }}>change</button> 64 </> 65 ); 66};
1// You can also subscribe to a non-lifecycle data monitor directly. 2const unsub = store.subscribe(() => { 3 // ... to do anything 4}, ["count", "text"]); 5 6// cancel subscirbe 7// unsub();
1store.subscribe(() => { 2 // ... to do anything 3}, []); 4// [] or no state keys is equal 5// no state keys 6store.subscribe(() => { 7 // ... to do anything 8});
1import { useEffect } from "react"; 2import { useStore } from "resy"; 3 4function App() { 5 const { count } = store.useStore(); 6 7 // Here is an example of a function component. 8 // If it is a class component, it can be used in componentDidMount. 9 useEffect(() => { 10 /** 11 * @param listener: subscription monitoring callback function 12 * @param stateKeys: subscription listens for changes in certain data fields of a specific store. 13 * If empty, default listens for changes in any one of the data in store. 14 * @return Unsubscribe: unsubscribe to the function of listening 15 */ 16 const unsubscribe = store.subscribe(({ 17 effectState, prevState, nextState, 18 }) => { 19 /** 20 * effectState:Currently changing data 21 * nextState:Data after change 22 * prevState:Data before change 23 */ 24 console.log(effectState, prevState, nextState); 25 }, ["count", "text"]); 26 27 // unsubscribe(); 28 return () => { 29 unsubscribe(); 30 // ... to do else anything 31 }; 32 }, []); 33 34 function btnClickA() { 35 store.count++; 36 } 37 38 function btnClickB() { 39 store.text = "control btn-b click update text state value"; 40 } 41 42 function btnClickC() { 43 store.setState({ 44 count: count + 1, 45 text: "control btn-c click update text state value", 46 }); 47 } 48 49 return ( 50 <> 51 <p>{count}</p> 52 <button onClick={btnClickA}>btn-A</button><br/> 53 <button onClick={btnClickB}>btn-B</button><br/> 54 <button onClick={btnClickC}>btn-C</button> 55 </> 56 ); 57}
1import { useEffect } from "react"; 2import { useStore, useSubscription } from "resy"; 3 4function App() { 5 const { count } = store.useStore(); 6 7 useSubscription(store, ({ 8 effectState, prevState, nextState, 9 }) => { 10 console.log(effectState, prevState, nextState); 11 }, ["count"]); 12 13 function btnClick() { 14 store.count++; 15 } 16 17 return ( 18 <> 19 <p>{count}</p> 20 <button onClick={btnClick}>btn</button><br/> 21 </> 22 ); 23}
1import { useEffect } from "react"; 2import { useStore } from "resy"; 3 4function App() { 5 const { count } = store.useStore(); 6 7 store.useSubscription(({ 8 effectState, prevState, nextState, 9 }) => { 10 console.log(effectState, prevState, nextState); 11 }, ["count"]); 12 13 function btnClick() { 14 store.count++; 15 } 16 17 return ( 18 <> 19 <p>{count}</p> 20 <button onClick={btnClick}>btn</button><br/> 21 </> 22 ); 23}
1import { useStore } from "resy"; 2 3function App() { 4 const { count, text } = store.useStore(); 5 6 return ( 7 <> 8 <div>{count}-{text}</div> 9 <div 10 onClick={() => { 11 // data recover initial 12 store.restore(); 13 // You can also add callback functions in the restore function 14 // store.restore(nextState => { 15 // console.log(nextState); 16 // }); 17 }} 18 > 19 reset-btn 20 </div> 21 </> 22 ); 23}
1import { createStore, useStore } from "resy"; 2 3const timeStore = createStore(() => { 4 return { 5 now: Date.now(), 6 }; 7}); 8 9function App() { 10 const { now } = useStore(timeStore); 11 12 return ( 13 <> 14 <div>now:{now}</div> 15 <div 16 onClick={() => { 17 // time data now recover and also changed initial, 18 // because of initialState is function return. 19 store.restore(); 20 }} 21 > 22 reset-btn 23 </div> 24 </> 25 ); 26}
1function App() { 2 return ( 3 <button 4 onClick={() => { 5 // Use less scenes, use it with caution 6 // You can change the unmountRestore parameter setting of createStore 7 store.setOptions({ unmountRestore: false }); 8 }} 9 > 10 btn 11 </button> 12 ); 13}
MIT License (c) 刘善保
No vulnerabilities found.
No security vulnerabilities found.