Use actions for asynchronous data operations, for example REST API calls.
The context
argument is an object with two keys - mutations
and actions
. You can use it to dispatch another action that's dependent on your current action's data and to alter the current state.
const store = {
state: {
user: null,
posts: []
},
mutations: {
USER_SET (state, data) {
state.user = data
}
POSTS_SET (state, data) {
state.posts = data
}
},
actions: {
async USER_POSTS_FETCH (context, userId) {
const data = await userPostsCall(userId)
context.mutations.POSTS_SET(data)
}
async USER_FETCH (context) {
// fetch the current user
const user = await userApiCall()
context.mutations.USER_SET(user)
// find out their ID and based on that dispatch an action to fetch their posts
context.actions.USER_POSTS_FETCH(user.id)
}
}
}
useAction
useAction<T>(actionName: string) => (args?: any) => Promise<T>
To use an action in a component, use the useAction()
hook. 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 { useEffect } from 'react'
import { useAction, useGetter } from 'vuex-but-for-react'
const UserComponent = () => {
const onUserFetch = useAction('USER_FETCH');
useEffect(() => {
onUserFetch();
}, [onUserFetch])
const user = useGetter('user');
return (
...
)
}
useActions
useActions(values: string[]) => ((args?: any) => Promise<any>)[]
If you wish to use more actions in a component, you can use the useActions()
hook instead of using useAction() multiple times. The returned functions will be in the same order as provided arguments.
const [handleUserFetch, handlePostsFetch] = useActions(['USER_FETCH', 'USER_POSTS_FETCH']);
useActionOnMount
useActionOnMount<T>(actionName: string, ...params: any[]) => void;
The hook useActionOnMount()
was created for user's convenience, where the action will execute on component mount only, unless the provided parameters change. Each parameter change will trigger a re-fetch. This saves the user the need to write useEffect
code and serves as a wrapper for it.
import { useActionOnMount, useGetter } from 'vuex-but-for-react'
const UserComponent = () => {
useActionOnMount('USER_FETCH');
const user = useGetter('user');
return (
...
)
}
useAction with modules
To access a module's action, use the module name as the prefix.const action = useAction('counter/COUNTER_FETCH')
const store = {
state: {
...
},
mutations: {
...
},
modules: {
counter: {
state: { count: 0 },
mutations: {
COUNTER_SET (state, newValue) {
state.count = newValue
}
},
actions: {
async COUNTER_FETCH (context) {
const data = await dummyApiCall()
// a module does not have access to the parent actions and mutations
context.mutations.COUNTER_SET(data)
}
}
}
}
}