npm i redux vue-redux-hooks
yarn add redux vue-redux-hooks
// store.ts
import { createStore, AnyAction } from 'redux'
function todos(state: string[] = [], action: AnyAction) {
switch (action.type) {
case 'ADD_TODO':
return state.concat([action.text])
default:
return state
}
}
export const store = createStore(todos, ['Use Redux'])
// after augmenting ComponentCustomProperties all other typings are not required
declare module 'vue' {
interface ComponentCustomProperties {
$redux: { store: typeof store; state: ReturnType<typeof store.getState> }
}
}
// main.ts
import { createApp } from 'vue'
import { install } from 'vue-redux-hooks'
import { store } from './store'
createApp(App).use(install(store)).mount('#app')
// App.vue
import { mapState } from 'vue-redux-hooks'
export default {
data() {
return {
search: 'Today',
}
},
computed: {
...mapState<{ search: string }>()({
filteredTodos(todos: State) {
return todos.filter((todo) => todo.includes(this.search))
},
}),
// or
filteredTodos() {
return this.$redux.state.filter((todo) => todo.includes(this.search))
},
},
}
// App.vue
import { mapDispatch } from 'vue-redux-hooks'
export default {
methods: {
...mapDispatch()({
addTodo: (text: string) => ({
type: 'ADD_TODO',
text,
}),
}),
// or
addTodo(text: string) {
return this.$redux.store.dispatch({
type: 'ADD_TODO',
text,
})
},
},
}
// App.vue
import { useStore } from 'vue-redux-hooks'
export default {
setup() {
const store = useStore<Store>()
const initialState = store.getState()
return { initialState }
},
}
// App.vue
import { useSelector } from 'vue-redux-hooks'
export default {
setup() {
const search = ref('Today')
const filteredTodos = useSelector((todos: State) =>
todos.filter((todo) => todo.includes(search.value)),
)
return { filteredTodos }
},
}
// App.vue
import { useDispatch } from 'vue-redux-hooks'
export default {
setup() {
const dispatch = useDispatch<Dispatch>()
const addTodo = (text: string) =>
dispatch({
type: 'ADD_TODO',
text,
})
return { addTodo }
},
}
// pokemonApi.ts
// Need to use the Vue-specific entry point to allow generating Vue hooks
import { createApi } from 'vue-redux-hooks'
import { fetchBaseQuery } from '@reduxjs/toolkit/query'
import type { Pokemon } from './types'
// Define a service using a base URL and expected endpoints
export const pokemonApi = createApi({
reducerPath: 'pokemonApi',
baseQuery: fetchBaseQuery({ baseUrl: 'https://pokeapi.co/api/v2/' }),
endpoints: (builder) => ({
getPokemonByName: builder.query<Pokemon, string>({
query: (name) => `pokemon/${name}`,
}),
}),
})
// Export hooks for usage in function components, which are
// auto-generated based on the defined endpoints
export const { useGetPokemonByNameQuery } = pokemonApi
// App.vue
import { toRefs, ref } from 'vue'
import { useGetPokemonByNameQuery } from './pokemonApi'
export default {
setup() {
const name = ref('Pikachu')
const skip = ref(false)
const query = useGetPokemonByNameQuery(name, {
refetchOnReconnect: true,
skip,
})
return { name, skip, ...query }
},
}