Update mapStateToProps with Ramda - ramda.js

The following entry is used in project, it's clear that state argument use quite often
const props = state => ({
name: getUserName(state),
role: getUserRole(state),
region: getUserRegion(state),
});
How can I update it with ramda?

You can use R.applySpec:
const mapStateToProps = R.applySpec({
name: getUserName,
role: getUserRole,
region: getUserRegion,
});

Related

Pinia shared reactivity in stores

Is it possible to share reactive state between stores in Pinia, for example:
export const useMainStore = defineStore('mainStore', {
state: () => ({
data: [{name: "some name", amount: useSomeStore().amount}]
}),
export const useSomeStore = defineStore('someStore', {
state: () => ({
amount: 0
}),
The idea is that useSomeStore.amount value is synced with the useMainStore data value.
So when I change the amount in useSomeStore to 5 I expect that data value in useMainStore will change accordingly to:
[{name: "some name", amount: 5}]
I know that I can subscribe to the store or use watchers but is there a better solution for this?
I made working solution using storeToRefs but not sure if there are drawbacks to this.
https://codesandbox.io/s/competent-breeze-wylkoj?file=/src/stores/tomato.ts
Remember pinia states are reactive objects.
Therefore, you can always set a computed on one of them which references another store's state.
Generic example:
const useStoreOne = defineStore('one', {
state: () => ({
foo: 'bar'
})
})
const useStoreTwo = defineStore('two', {
state: () => ({
foo: computed({
get() { return useStoreOne().foo },
set(val) { useStoreOne().foo = val }
})
})
})
Note: storeToRefs does the same as above. So you can write storeTwo as:
const useStoreTwo = defineStore('two', {
state: () => ({
foo: storeToRefs(useStoreOne()).foo
})
})
But it's kind of pointless. Why would you want to use useStoreTwo().foo anywhere instead of using useStoreOne().foo directly?
Make no mistake: the above pattern sets a two-way binding between the two store's foos. But, the second store's foo is useless. Anywhere you use it, you could be using the first one's foo directly.
On general principles, when you come across this pattern (or across the need for it), it should raise a flag: you're using state management because you want "one source of truth". Not more.

make redux toolkit query inside useEffect

I am receiving a cat prop and want to fetch data from api whenever cat is changed using RTK query. But it's getting error the following error:
React Hook "useGetProductsQuery" cannot be called inside a callback".
How to make a RTK query whenever cat is changed?
const Products = ({cat,filter,sort}) => {
const [products, setproducts] = useState([])
const [filters, setFilters] = useState([])
useEffect(()=>{
const {data,isError,isLoading}=useGetProductsQuery()
console.log(data,isError,isLoading)
},[cat])
}
import { createApi, fetchBaseQuery }
from'#reduxjs/toolkit/query/react';
const baseUrl=process.env.REACT_APP_ECOMMERCE_API_URL
const createRequest = (url) => ({ url });
export const ecommApi = createApi({
reducerPath: 'ecommApi',
baseQuery: fetchBaseQuery({baseUrl}),
endpoints: (builder) => ({
getProducts: builder.query({
query: () => createRequest("/api/v1/products")
}),
})
})
export const{useGetProductsQuery}=ecommApi;
Why not just pass cat as an argument to the useQuery hook without the useEffect?
That will make a new request every time cat changes.
const {data,isError,isLoading}=useGetProductsQuery(cat)
As an addition to phry's answer:
If "cat" might be undefined use the skip parameter for conditional fetching:
const {data,isError,isLoading} = useGetProductsQuery(cat, {skip: !cat})
See https://redux-toolkit.js.org/rtk-query/usage/conditional-fetching

Getting unknown local action type in Vuex Store

I have broken up my Vuex store into namespaced modules.
I have created a User module, where I need to call my Showrooms module. The interesting thing, is that this action works fine. But I am updating the store:
dispatch('showrooms/updateLocalShowroom',
{
weddingId: element.wedding.id,
showroomDresses: element.showroom.showroomDresses,
status: element.showroom.status,
uuid: element.showroom.uuid,
},
{
root: true
}
)
But when I try and reset the Showrooms store with this:
dispatch('showrooms/resetShowrooms', { root: true })
I get the following error:
[vuex] unknown local action type: showrooms/resetShowrooms, global type: user/showrooms/resetShowrooms
The only thing I can think of is something is that when I resetShowrooms I do it like this in my store module:
This action:
resetShowrooms: ({ commit }) => {
commit('zeroOutShowrooms')
},
Calls this mutation
zeroOutShowrooms: (state) => {
Vue.set(state, 'showrooms', [])
}
It ends up that dispatch is looking for some data in the second position. That's why this was NOT working:
resetShowrooms: ({ commit }) => {
commit('zeroOutShowrooms')
},
While this DID work and solved my issue:
dispatch('showrooms/resetShowrooms', '', { root: true })
Just sending the empty string did the trick and all is good now.

Can I access flags added by package #nuxtjs/device from the store?

I'm trying to initialize a store state variable with a flag generated by #nuxtjs/device:
export const state = () => ({
isMenuVisible: !$device.isMobile
});
This doesn't work though, I'm getting this error message:
$device is not defined
Any suggestion?
you missed 'this'
export const state = () => ({
isMenuVisible: !this.$device.isMobile
});

Redux store overwritten instead of merged

I am writing an app in React Native using Redux. When I execute an action, instead of updating the store, it seems to replace the store, defining only the values that are explicitly stated in my reducer.
I am using handleActions from the redux-actions package. An example reducers looks like this;
import { handleActions } from 'redux-actions';
export default handleActions({
DOCUMENT_GET_ALL_PENDING: state => ({
isRefreshing: true,
}),
DOCUMENT_GET_ALL_FULFILLED: (state, action) => ({
document: action.payload.documents,
isRefreshing: false,
}),
}, { isRefreshing: false, documents: [] });
For example, when it reacht DOCUMENT_GET_ALL_PENDING, the documents array gets set to undefined.
Here is what the creation of my store looks like;
I am using redux-promise-middleware, redux-devtools-extension and thunk middleware.
const store = createStore(
rootReducer,
defaultState,
composeWithDevTools(applyMiddleware(promiseMiddleware(), thunk)),
);
Any and all help or suggestions is welcome.
You need to merge your states with the previous one. Right now you're just returning the new state values.
There are many ways to do it but you can use the es6 spread operator.
DOCUMENT_GET_ALL_PENDING: state => ({
...state,
isRefreshing: true,
}),
DOCUMENT_GET_ALL_FULFILLED: (state, action) => ({
...state,
document: action.payload.documents,
isRefreshing: false,
})