How to access DVA Store in UMI application? - redux

Hi most of the react developers would find dvaJS and umiJS, heaven for state management and application development. Dva is elm based state management tool that use react-redux for state management.
Q: How to access DVA Store in UMI application, outside the component or without connect?
Q: How to dispatch DVA Store in UMI application, outside the component or without connect?

Q: How to access DVA Store in UMI application, outside the component or without connect?
A: https://v2.umijs.org/guide/with-dva.html#how-to-access-store-or-dispatch
It says use:
window.g_app._store
Q: How to dispatch DVA Store in UMI application, outside the component or without connect?
A: https://v2.umijs.org/guide/with-dva.html#how-to-access-store-or-dispatch
It says use:
window.g_app._store.dispatch('namespace/action')
Bonus:
Q: How to get state of DVA Store in UMI application, outside the component or without connect?
A: https://v2.umijs.org/guide/with-dva.html#how-to-access-store-or-dispatch
It says use:
window.g_app._store.getState()
Available Functions:
asyncReducers: {}
dispatch: ƒ ()
getState: ƒ f()
replaceReducer: ƒ (n)
runSaga: ƒ ()
subscribe: ƒ subscribe(listener)
Recommended: Instead of directly using it, write a Util that exports these functions.

To access or dispatch DVA store in UMI app, you can use DVA hooks in functional components without connect. It can be only used with DVA v2.6.x.
In a functional component:
Access store:
const state = useSelector(state => state)
// If state in DVA store changed, rendered values in "state" can be changed in page too.
or
const store = useStore()
const state = store.getState()
// If state in DVA store changed, rendered values in "state" won't be changed in page.
Dispatch:
const dispatch = useDispatch()
dispatch({type: "namespace/action", payload: 12345})

As and extra reference and for those searching for accessing the dva app reference outside of a react component context while using:
Umi.js v3+
Along with dva 2.6+ (as per the framework compatibility)
You can use the getDvaApp exported method:
import { getDvaApp } from 'umi';
const dispatch = getDvaApp()._store.dispatch;
// use the `dispatch`

Related

Redux and NextJS 13

I am trying to build NextJs app with 13th version of next and redux.
I found the way to pass redux provider in app, but I still don't understand next thing:
How can I use "createAsyncThunk" actions or RTK query with "getStaticProps" and another next functions for fetching data in nextJS 13 and app folder?
getServerSideProps and getStaticProps run on the server so they do not have any relation with your components and your hooks, so there is no way that they have access to the redux provider
but since getServerSideProps runs on every request you can use the request the pass data to it. one solution is to pass data in the url.
let suppose that you have page A with getServerSideProps you can call it like this :
const router = useRouter();
router.push({
pathname: '/url_of_page_A',
query: {
data: JSON.stringify( { a: 'value', b: 'another value'} ) ;
},
});
Now in your page A inside getServerSideProps you can access data via context query
export async function getServerSideProps(context) {
const data = JSON.parse(context.query.data);
}

Handling namespaced modular approach on PINIA, Vue3+Typescript

normally I was using namespaced vuex. But I am deciding to quit vuex because Pinia has the vue core team support. I think it's better for the future developements. Now I am creating store with a modular approach but couldn't really understand how to handle that part on typescript project.
let's say I have a user interface.
interface User {
email: string,
username: string,
}
export default User;
and in store/modules/state.ts I am calling the Type and creating a user state.
import User from "../../types/User"
export const state = () => {
return {
user: {} as User | null,
};
}
and in store/modules/index.ts I should import the state. And make the namespace: true then export it for the defineStore() for pinia store.
import {state} from "./state"
export default {
namespace: true,
state,
}
in store/index.ts
import {defineStore} from "pinia"
import {data} from "./modules"
export const Store = defineStore(data)
okay above, namespace part I use the vuex way. But what is the right approach for the pinia. Additionally, getters and actions as well. How should export and use them.
According to official Pinia docs:
Vuex has the concept of a single store with multiple modules. These modules can optionally be namespaced and even nested within each other. The easiest way to transition that concept to be used with Pinia is that each module you used previously is now a store.
So now you should think about each vuex module as an separated pinia store. Looking at your example it could look like this. create file in store/modules/index.ts and paste:
import { defineStore } from "pinia";
import state from "store/modules/state.ts"; // Assuming that it's path to user state
export const useUserStore = defineStore('some/vuex/module/name', {
state: state,
getters: {
// your getters here, check the Offical Pinia above
},
actions: {
// your actions and mutations here, also check the offical Pinia Docs
}
})
If you want to split getters, actions and state into multiple files, there is discussion on offical repo issue where I provided example, that is working for me. Here is a link

Why Not "pre-connect" Redux Action Creators?

In a typical React/Redux codebase you have action creator functions like:
Actions.js:
export const addFoo = foo => ({ foo, type: 'ADD_FOO' });
Then you use connect to create a version of that function which dispatches the action, and make it available to a component:
Component.js:
import { addFoo } from 'Actions';
const mapPropsToDispatch = { addFoo };
const SomeComponent = connect(mapStateToProps, mapPropsToDispatch)(
({ addFoo }) =>
<button onClick={() => addFoo(5)}>Add Five</button>;
)
I was thinking, rather than mapping each action creator to its dispatched version inside the connect of every component that uses them, wouldn't it be simpler and cleaner if you could just "pre-connect" all of your action creators ahead of time:
Store.js:
import { createStore } from 'redux'
const store = createStore(reducer, initialState);
export const preConnect = func => (...args) => store.dispatch(func(...args));
Actions.js (2.0):
import { preConnect } from 'Store';
export const addFoo = preConnect(foo => ({ foo, type: 'ADD_FOO' }));
Component.js (2.0):
import { addFoo } from 'Actions';
const SomeComponent = () =>
<button onClick={() => addFoo(5)}>A Button</button>;
Am I missing any obvious reason why doing this would be a bad idea?
You make a reference to the dispatch() function in your code here:
export const preConnect = func => (...args) => store.dispatch(func(...args));
But in the world of React-Redux there is no direct reference to the dispatch() function inside of our components. So what's going on?
When we pass our action creator into the connect() function, the connect() function does a special operation on the functions inside the actions object.
export default connect(mapStateToProps, { selectSong })(SongList);
The connect() function essentially wraps the action into a new JavaScript function. When we call the new JavaScript function, the connect() function is going to automatically call our action creator, take the action that gets returned and automatically call the dispatch() function for us.
So by passing the action creator into the connect() function, whenever we call the action creator that gets added to our props object, the function is going to automatically take the action that gets returned and throw it into dispatch function for us.
All this is happening behind the scenes and you don't really have to think about it when using the connect() function.
So thats how redux works, there is a lot of wiring up and its one of the chief complaints I believe people have around this library, so I do understand your sentiment of wanting to pre-configure some of its setup and in this case, in my opinion, the toughest part of the Redux setup which is wiring up the action creators and reducers.
The problem with pre-configuring I am thinking is that the developer still needs to know how to write these functions and then manually hook them together as opposed to how its done in other state management libraries and if that is taken away by some type of pre-configuration process, Redux becomes more magical and harder to troubleshoot I think. Again the action creators and reducers are the biggest challenge in putting together a Redux architecture and so mastering and knowing how to troubleshoot that area almost requires manual setup to do so.

Cant create connected containers or enhancers for griddle

I'm trying to create an Enhancer for griddle v1.6.0.
I am getting this error:
Uncaught Error: Could not find "store" in either the context or props
of "Connect(Row)". Either wrap the root component in a , or
explicitly pass "store" as a prop to "Connect(Row)".
Here is my Enhancer
import { connect } from 'react-redux';
import { selectors } from 'griddle-react';
const { rowDataSelector } = selectors;
export default connect((state, ownProps) => ({
hello: 'world!',
RDZ: rowDataSelector(state, ownProps)
}));
I have a similar problem if I try to create my own Container
EDIT
It appears that the connect is actually connecting to my app's store (which I haven't added a provider for) instead of griddle's internal store. I'm not sure how to access griddle's internal store in an enhancer, or container... Maybe I am missing something here, should I be adding selectors instead?
This a current limitation/bug with Griddle (I think).
I worked around this by passing by data from the app redux to simple component, then that component hands the data to Griddle.
This is not ideal, but works for now.
This discussion maybe of some help.
https://github.com/GriddleGriddle/Griddle/issues/647

React + MobX - not re-rendering update to state

I've setup a new sample/boilerplate project for testing out using Meteor with React & MobX (using Mantra architecture). The project is at https://github.com/markoshust/mantra-matui-mobx
I'm having an issue where the state change of the State.header.title property is not properly reflecting the updated state change on re-render.
My state is built by pulling in simple objects:
https://github.com/markoshust/mantra-matui-mobx/blob/master/client/modules/core/stores/route.js
Into one master observable object:
https://github.com/markoshust/mantra-matui-mobx/blob/master/client/main.js#L8
I'm listing for route change and calling an action to update state:
https://github.com/markoshust/mantra-matui-mobx/blob/master/client/modules/core/reactions/route.js#L10
This action updates state:
https://github.com/markoshust/mantra-matui-mobx/blob/master/client/modules/core/actions/route.js#L5
The console is logging out proper state change, so the state is being updated properly. However, the component is not being re-rendered with the updated state (this line is console.log'ing old state val):
https://github.com/markoshust/mantra-matui-mobx/blob/master/client/modules/core/containers/Header.js#L6
I'm seeing the 'updating...' message, so the component is re-rendering, but it appears to still be pulling in the old state. I did add observer to all of my react components:
https://github.com/markoshust/mantra-matui-mobx/blob/master/client/modules/core/components/Header.js
I needed to create a custom composer for MobX. I added a listen for autorun to re-compose the component.
https://github.com/markoshust/mantra-matui-mobx/blob/master/client/modules/core/libs/with_mobx.js
import { compose } from 'mantra-core';
import { autorun } from 'mobx';
export default function composeWithMobx(fn, L, E, options) {
const onPropsChange = (props, onData) => {
const reactiveFn = () => fn(props, onData);
autorun(reactiveFn);
return reactiveFn();
};
return compose(onPropsChange, L, E, options);
}

Resources