
Product
Redesigned Repositories Page: A Faster Way to Prioritize Security Risk
Our redesigned Repositories page adds alert severity, filtering, and tabs for faster triage and clearer insights across all your projects.
@airma/react-effect
Advanced tools
@airma/react-effect
is an asynchronous state-management tool for react.
API useQuery
can query data, and set it as a state.
import React from 'react';
import {useQuery} from '@airma/react-effect';
import {User} from './type';
type UserQuery = {
name: string;
username: string;
}
// Prepare a query promise callback.
const fetchUsers = (query: UserQuery):Promise<User[]> =>
Promise.resolve([]);
const App = ()=>{
const [query, setQuery] = useState({name:'', username:''});
const [state, trigger, executeWithParams] = useQuery(
// Use query callback
fetchUsers,
// Set parameters for query callback
[query]
);
const {
// User[] | undefined
data,
// boolean
isFetching,
// any
error,
// boolean
isError,
// boolean
loaded
} = state;
......
}
When useQuery
is mounted, or the dependency parameters change, it calls the promise callback.
API useMutation
is similar with useQuery
. The difference is that it should be triggered manually to work.
import React from 'react';
import {useMutation} from '@airma/react-effect';
import {User} from './type';
const saveUser = (user: User): Promise<User> =>
Promise.resolve(user);
const App = ()=>{
const [user, setUser] = useState<User>({...});
const [
state,
trigger,
executeWithParams
] = useMutation(
// Set mutation callback,
// it is a promise callback.
saveUser,
// Set mutation parameters.
[ user ]
);
const {
// User | undefined
data,
// boolean
isFetching,
// any
error,
// boolean
isError
} = result;
const handleClick = ()=>{
// trigger mutation execute with variables [User]
trigger();
}
......
}
The state of useMutation has same fields with useQuery state.
Both of useQuery and useMutation need a promise callback for working, the mission of promise callback is called session.
Use a simplified API session to make coding clear.
import React from 'react';
import {session} from '@airma/react-effect';
import {User} from './type';
type UserQuery = {
name: string;
username: string;
}
// use `session` API to declare a query session
const userQuerySession = session(
(query: UserQuery):Promise<User[]> =>
Promise.resolve([]),
'query'
);
const App = ()=>{
const [query, setQuery] = useState({name:'', username:''});
const [
state,
trigger,
executeWithParams
// call session.useQuery
] = userQuerySession.useQuery(
// Set parameters for query callback
[query]
);
const {
// User[] | undefined
data,
// boolean
isFetching,
// any
error,
// boolean
isError,
// boolean
loaded
} = state;
......
}
The state of useQuery/useMutation is a local state. There are two different store state-managements: dynamic store or static store.
import React from 'react';
import {session, provide} from '@airma/react-effect';
import {User} from './type';
type UserQuery = {
name: string;
username: string;
}
// declare a query session dynamic store
const userQueryKey = session(
(query: UserQuery):Promise<User[]> =>
Promise.resolve([]),
'query'
).createKey();
const SearchButton = ()=>{
// useSession subscribes state change from session store
const [
// state from session store
{isFetching},
// call trigger function to make useQuery work manually
triggerQuery
] = userQueryKey.useSession();
return (
<button
disabled={isFetching}
onClick={triggerQuery}
>
query
</button>
);
}
// provide keys to create a dynamic store in component
const App = provide(userQueryKey).to(()=>{
const [query, setQuery] = useState({name:'', username:''});
const [
state,
// Write every query state change to store
] = userQueryKey.useQuery(
[query]
);
......
return (
<>
<SearchButton />
......
</>
);
})
A dynamic store should be created in a component, and synchronized in the children components by using React.Context
.
A static store should be created in a global scope, and used in any component without provider.
import React from 'react';
import {session} from '@airma/react-effect';
import {User} from './type';
type UserQuery = {
name: string;
username: string;
}
// create a static store for session
const userQueryStore = session(
(query: UserQuery):Promise<User[]> =>
Promise.resolve([]),
'query'
).createStore();
const SearchButton = ()=>{
const [
{
isFetching,
// User[] | undefined
data
},
triggerQuery
] = userQueryStore.useSession();
return (
<button
disabled={isFetching}
onClick={triggerQuery}
>
query
</button>
);
}
// a static store needs no Provider.
const App = ()=>{
const [query, setQuery] = useState({name:'', username:''});
const [
state
] = userQueryStore.useQuery(
[query]
);
......
return (
<>
<SearchButton />
......
</>
);
}
The state data
from useSession is always has a undefined
union type. API useLoadedSession can be helpful if the session state.data
is not empty from initializing time.
import React from 'react';
import {session} from '@airma/react-effect';
import {User} from './type';
type UserQuery = {
name: string;
username: string;
}
const userQueryStore = session(
(query: UserQuery):Promise<User[]> =>
Promise.resolve([]),
'query'
).createStore();
const SearchButton = ()=>{
// store.useLoadedSession can give out the promise resolve type without `empty`.
const [
{
isFetching,
// User[]
data
},
triggerQuery
] = userQueryStore.useLoadedSession();
return (
<button
disabled={isFetching}
onClick={triggerQuery}
>
query
</button>
);
}
const App = ()=>{
const [query, setQuery] = useState({name:'', username:''});
const [
state
] = userQueryStore.useQuery(
// use object config to set default data
{
variables: [query],
// To make `state.data` not empty,
// a default data is needed.
defaultData: []
}
);
......
return (
<>
<SearchButton />
......
</>
);
}
Want to do something when query or mutation responses?
import React from 'react';
import {session, useResponse} from '@airma/react-effect';
import {User} from './type';
type UserQuery = {
name: string;
username: string;
}
const userQuerySession = session(
(query: UserQuery):Promise<User[]> =>
Promise.resolve([]),
'query'
);
const App = ()=>{
const [query, setQuery] = useState({name:'', username:''});
const [
state
] = userQuerySession.useQuery(
[query]
);
// When useQuery/useMutation responses,
// useResponse calls the response callback.
useResponse(
// response callback
(sessionState)=>{
// accept a newest session state.
const {
data,
isError,
error,
......
} = sessionState;
doSomething(sessionState);
},
// listen to the session state of useQuery
state
);
// When useQuery/useMutation responses successfully,
// useResponse.useSuccess calls the response callback.
useResponse.useSuccess(
(data, sessionState)=>{
// accept a newst session state data.
// accept a newest session state.
doSomething(data);
},
// listen to the session state of useQuery
state
);
// When useQuery/useMutation responses unsuccessfully,
// useResponse.useFailure calls the response callback.
useResponse.useFailure(
(error, sessionState)=>{
// accept a newst session state error.
// accept a newest session state.
doSomething(error);
},
// listen to the session state of useQuery
state
);
......
}
Want to run useQuery or useMutation with some features like debounce?
import React from 'react';
import {session, Strategy} from '@airma/react-effect';
import {User} from './type';
type UserQuery = {
name: string;
username: string;
}
const userQuerySession = session(
(query: UserQuery):Promise<User[]> =>
Promise.resolve([]),
'query'
);
const App = ()=>{
const [query, setQuery] = useState({name:'', username:''});
const [
state,
trigger,
executeWithParams
] = userQuerySession.useQuery(
{
variables: [query],
// set a debouce strategy to take debounce query feature.
strategy: Strategy.debounce(300)
}
);
......
}
The Strategy API contains some useful strategies for useQuery and useMutation. Compose some strategies together can make the session of useQuery/useMutation performance wonderfully.
import React from 'react';
import {session, Strategy} from '@airma/react-effect';
import {User} from './type';
type UserQuery = {
name: string;
username: string;
}
const userQuerySession = session(
(query: UserQuery):Promise<User[]> =>
Promise.resolve([]),
'query'
);
const App = ()=>{
const [query, setQuery] = useState({name:'', username:''});
const [
state,
trigger,
executeWithParams
] = userQuerySession.useQuery(
{
variables: [query],
// compose different strategies.
strategy: [
// Validate query.name is not empty,
// if it is empty, then stop execute query
Strategy.validate(()=>!!query.name),
// Query with debounce feature
Strategy.debounce(300),
// If the response data equals current state.data,
// keeps current state.data.
Strategy.memo()
]
}
);
......
}
Want to use SWR(stale-while-revalidate)?
import React from 'react';
import {session, Strategy} from '@airma/react-effect';
import {User} from './type';
type UserQuery = {
name: string;
username: string;
}
const userQuerySession = session(
(query: UserQuery):Promise<User[]> =>
Promise.resolve([]),
'query'
);
const App = ()=>{
const [query, setQuery] = useState({name:'', username:''});
const [
state,
trigger,
executeWithParams
] = userQuerySession.useQuery(
{
variables: [query],
strategy: [
// use swr strategy
Strategy.cache({
capacity:10,
staleTime:5*60*1000
})
]
}
);
......
}
@airma/react-effect
is an asynchronous state-management tool for react. It dependents @airma/react-state, and there are some similar apis between both packages, so, use a common package @airma/react-hooks is a better choice.
Setting state in asynchronous callback is more easy to take a stale state usage bug in code. And it often makes zombie-children problem too.
API useQuery works when it is mounted, or the dependency parameters change, just like React.useEffect performance. It also can be triggered manually.
The package lives in npm. To install the latest stable version, run the following command:
npm i @airma/react-effect
chrome: '>=91',
edge: '>=91',
firefox: '=>90',
safari: '>=15'
FAQs
This is a react async state management tool
The npm package @airma/react-effect receives a total of 27 weekly downloads. As such, @airma/react-effect popularity was classified as not popular.
We found that @airma/react-effect demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Product
Our redesigned Repositories page adds alert severity, filtering, and tabs for faster triage and clearer insights across all your projects.
Security News
Slopsquatting is a new supply chain threat where AI-assisted code generators recommend hallucinated packages that attackers register and weaponize.
Security News
Multiple deserialization flaws in PyTorch Lightning could allow remote code execution when loading untrusted model files, affecting versions up to 2.4.0.