react-reex
v1.1.2
Published
React-reex is a lightweight global state management solution for React and React-native. It depends on React and doesn't just use context-aware API and based on useState hook
Downloads
386
Maintainers
Readme
React-reex
React-reex is a lightweight global state management solution for React and React-native. It depends on React and doesn't use React Context API but only based on useState hook
Official documentation
Summary
- Installation
- Configuration
- States
- Getters
- Actions
- Mutations
- Hooks and utils
- Store persistent
- Module structure
1. Installation
a. YARN
yarn add react-reex@latest
b. NPM
npm install react-reex@latest --save
2. Configuration
You must to do the configuration below if you need to use it as global store.
a. CreateModule
In /store/counter/index.ts
import { createModule } from "react-reex"
const counterStore = createModule({
name: "counter",
state() {
return {
count: 0,
}
},
getters: {
double() {
return this.count * 2
},
},
actions: {
increment() {
this.commit("setCount", this.count + 1)
},
decrement(v: number) {
this.count--
},
},
mutations: {
setCount(value: number) {
this.count = value
},
},
events: {
count: {
handler(value) {
console.log("Count has changed", value)
},
},
},
})
export default counterStore
b. CreateStore
In /store/index.ts
import { createStore } from "react-reex"
import counterStore from "./counter"
const store = createStore({
modules: {
counterStore,
},
created() {
console.log("created global")
},
before(data) {
console.log("before global", data)
},
handler(state) {
console.log("handler global", state)
},
})
export const { useReexState, useReexGetter, useReexModule, useReexAction } = store
export default store
c. Import store folder in application main
In App.tsx
import React from "react"
import "../store" // Add this
export default function App() {
return <>{/* Your application code */}</>
}
3. States
Use useReexState()
hook to access your current state's values. Below is an example of store that we will use.
const counterStore = createModule({
state() {
return {
count: 0,
}
},
})
export default counterStore
useReexState
The states are used with the useReexState()
hook. Your component will be notified only of the change connected to your states.
- reactjs
import React from "react"
import { useReexState } from "../store"
const Counter = () => {
const count = useReexState("counter/count")
return <span>{count}</span>
}
- react-native
import React from "react"
import { Text } from "react-native"
import { useReexState } from "../store"
const Counter = () => {
const count = useReexState("counter/count")
return <Text>{count}</Text>
}
4. Getters
Use useReexGetter()
hook to access your current state's values. You can also use getters for computed logic. Below is an example of store that we will use.
import { createModule } from "react-reex"
const counterStore = createModule({
name: "counter",
state() {
return {
count: 0,
}
},
getters: {
double() {
return this.count * 2
},
},
actions: {
...
},
mutations: {
...
},
events: {
...
},
})
export default counterStore
useReexGetter
The getters are used with the useReexGetter()
hook. Your component will be notified only of the change connected to your getters.
- reactjs
import React from "react"
import { useReexGetter } from "../store"
const Counter = () => {
const double = useReexGetter("counter/double")
return <span>{double}</span>
}
- react-native
import React, { useEffect } from "react"
import { Text } from "react-native"
import { useReexGetter } from "../store"
const Counter = () => {
const double = useReexGetter("counter/double")
return <Text>{double}</Text>
}
5. Actions
Use actions for asynchronous data operations, for example REST API calls.
The this
scope is an object with five keys:
a. Use dispatch in a store
- state: this is the current state of the current store
- dispatch: to call another action that's dependent on your current action's data and to alter the current state.
- getState: to get any state in the current store or another
- getGetter: to get any getter in the current store or another
- commit: to call any mutation in the current store or another
import { createModule } from "react-reex"
const counterStore = createModule({
state() {
return {
count: 0,
}
},
getters: {
double() {
return this.count * 2
},
},
actions: {
increment() {
this.commit("setCount", 1)
},
incr() {
this.dispatch("increment")
},
},
mutations: {
setCount(value) {
this.count = value
},
},
})
export default counterStore
b. Use dispatch in a component
To use an action in a component, use the dispatch()
. Actions always return a promise. They don't get re-created, so you're safe with using them as dependencies for useEffect or useCallback.
import React, { useEffect } from "react"
import store from "../store"
const Counter = () => {
useEffect(() => {
store.dispatch("counter/increment")
}, [])
return <></>
}
6. Mutations
Use mutations to change your current state's values. Mutations are synchronous operations and can be called with the commit()
or inside an action.
a. Declare mutation in a store
Below is an example of store that we will use.
import { createModule } from "react-reex"
const counterStore = createModule({
state() {
return {
posts: [],
}
},
...
mutations: {
setPosts(data) {
this.posts = data
},
addPost(data) {
this.posts.unshift(data)
},
deletePostByIndex(index) {
this.posts = this.posts.filter((p, i) => i !== index)
},
},
})
export default counterStore
b. Use commit in a component
To use a mutation in a component, use the commit()
.
- reactjs
import React from "react"
import store from "../store"
const PostComponent = () => {
const handlePostAdd = () => {
store.commit("counter/addPost", {
id: 1,
title: "New post to be added",
body: "Awesome text inside",
})
}
return <button onClick={handlePostAdd}>Add new post</button>
}
- react-native
import React from "react"
import { Button } from "react-native"
import store from "../store"
const PostComponent = () => {
const handlePostAdd = () => {
store.commit("counter/addPost", {
id: 1,
title: "New post to be added",
body: "Awesome text inside",
})
}
return <Button onPress={handlePostAdd} title='Add new post' color='#841584' />
}
7. Hooks and utils
a. useReexModule
useReexModule
as custom hooks
import { createModule } from "react-reex"
const counterStore = createModule({
name: "counter",
state() {
return {
count: 0,
}
},
getters: {
double() {
return this.count * 2
},
},
actions: {
...
},
mutations: {
...
},
events: {
...
},
})
export default counterStore
function CounterComponent() {
const { state } = useReexModule('counter')
return (
<div>{state.count}</div>
)
}
b. useMounted
import React from "react"
import { useMounted } from "react-reex"
function MyComponent() {
useMounted(() => {
console.log("Component mounted")
})
return <></>
}
c. useFetch
import React, { useEffect } from "react"
import { useFetch } from "react-reex"
function CButton() {
const fetch = useCallback(async function () {
return {
message: "done",
}
}, [])
const { fetcher, loading, data } = useFetch(fetch)
useEffect(() => {
console.log(loading)
}, [loading])
return <button onClick={fetcher}>RUN</button>
}
d. resetStore
use resetStore
function to reset all store
reactjs
import React, { useCallback } from "react"
import { resetStore } from "react-reex"
function MyComponent() {
const reset = useCallback(() => {
resetStore()
}, [resetStore])
return <button onClick={reset}>Reset store</button>
}
react-native
import React, { useCallback } from "react"
import { resetStore } from "react-reex"
function MyComponent() {
const reset = useCallback(() => {
resetStore()
}, [resetStore])
return <Button onPress={reset} title='Reset store' />
}
e. getGetter
import { useEffect } from "react"
import store from "../store"
function MyComponent() {
useEffect(() => {
const double = store.getGetter("counter/double")
console.log("Getter value :", double)
}, [])
return <></>
}
f. getState
Below is an example of store that we will use.
const counterStore = createModule({
state() {
return {
count: 0,
}
},
getters: {
double() {
return this.count * 2
},
},
actions: {
increment() {
this.commit("setCount", 1)
},
},
mutations: {
setCount(value) {
this.count = value
},
},
})
export default counterStore
import { useEffect } from "react"
import store from "../store"
function MyComponent() {
useEffect(() => {
const count = store.getState("count")
console.log("count value :", count)
}, [])
return <></>
}
g. useReexAction
Below is an example of store that we will use.
const counterStore = createModule({
state() {
...
},
getters: {
...
},
actions: {
async getMessage() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({ message: 'done' });
}, 2000)
});
},
},
mutations: {
...
},
})
export default counterStore
import { useEffect } from "react"
import store from "../store"
function MyComponent() {
const { data, fetcher, loading } = useReexAction("counter/getMessage")
useEffect(() => {
console.log("// --- //", loading)
}, [loading])
return (
<div>
{data && data.message && <span>{data.message}</span>}
<button onClick={fetcher}>Start</button>
</div>
)
}
h. subscribe
Below is an example of store that we will use.
const counterStore = createModule({
state() {
return {
count: 0,
}
},
getters: {
double() {
return this.count * 2
},
},
actions: {
increment() {
this.count++
},
},
})
export default counterStore
import store from "../store"
function CounterSubscribe() {
store.subscribe("counter/count", function ({ state }) {
console.log("Count updated", state.count)
})
return <></>
}
8. Store Persistent
a. All stores
In /store/index.ts
import { createStore } from "react-reex"
import counterStore from "./counter"
// import orderStore from "./order"
const store = createStore({
modules: {
counterStore,
// orderStore
},
created() {
console.log("created global")
},
before(data) {
console.log("before global", data)
},
handler(state) {
console.log("handler global", state)
},
})
// Add this
store.enablePersistStore({
setItem(d, v: any) {
localStorage.setItem(d, JSON.stringify(v))
},
getItem(d) {
return JSON.parse(localStorage.getItem(d) as string)
},
removeItem(d) {
return localStorage.removeItem(d)
},
})
export const { useReexState, useReexGetter, useReexModule, useReexAction } = store
export default store
b. Specific store
For example: In /store/counter
import { createModule } from "react-reex"
const counterStore = createModule({
state() {
return {
count: 0,
}
},
...
})
// Add this
counterStore.enablePersistStore({
setItem (d, v: any) {
localStorage.setItem(d, JSON.stringify(v))
},
getItem (d) {
return JSON.parse(localStorage.getItem(d) as string)
},
removeItem (d) {
return localStorage.removeItem(d)
},
})
export default counterStore
9. Module structure
All files with suffix /(\*?\.store\.(js|ts|jsx|tsx))$/
in src
folder will consider as store module and will combine with the global store.
- (root folder)
- package.json
- public
- src
- store
- counter
- index.ts
- user
- index.ts
- index.ts
- counter
- modules
- home
- page.tsx
- home.store.ts
- profile
- page.tsx
- profile.store.ts
- home
- store
In src/modules/home/home.store.ts
import { createModule } from "../reex";
const homeStore = createModule({
name: "home",
state: {
nbr: 0,
},
getters: {
double() {
return this.nbr * 2;
},
},
actions: {
increment(v: string[]) {
this.nbr++;
},
},
mutations: {
setCount(v: number) {
this.nbr = v;
}
},
});
export default homeStore;