Unique state in multiple instances of same component - nuxtjs3

Is there a way to make useState not to share the state between multiple instances of the same component without hacking the key argument with Math.random().
const activated = useState("activated", () => false)

I'd suggest to use useState if you want to share state. If you don't want to, you could use const activated = ref(false). You must not use it outside the setup function though.
const activated = () => useState(false) would be another option (see https://v3.nuxtjs.org/guide/features/state-management).

Related

Proper way of using Redux and RTKQ in NextJs with code-splitting

This is a topic that's been discussed a lot through github issues and by now I've noticed two main opinions: It's not possible or it should not be done at all.
The argument for both sides is that redux is not meant for it, that the .replaceReducer function is only meant for the purposes of hot-reloading (even though redux itself mentions it as a possibility for code-splitting).
The goal
Anyway, what I would like to achieve (ideally) is a system that only sends the relevant slices and relevant redux code for a specific route in NextJs. And (even more ideally) when navigating between pages the store should just get extended and not re-created.
My initial approach
My first idea was to implement a recipe from the link above, attaching and exposing the injectReducer function onto my store during the store setup:
const store = configureStore({
reducer: {
globals,
[rtkqApi.reducerPath]: rtkqApi.reducer
},
middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(rtkqApi.middleware)
});
store.dynamicReducers = {};
store.injectDynamicReducer = (name, reducer) => {
if (Object.keys(store.dynamicReducers).includes(name)) {
return;
}
store.dynamicReducers[name] = reducer;
store.replaceReducer(
combineReducers({
globals,
[rtkqApi.reducerPath]: rtkqApi.reducer,
...store.dynamicReducers
})
);
};
const makeStore = () => store;
export const wrapper = createWrapper(makeStore);
export const injectReducer = (sliceName, reducer) => store.injectDynamicReducer(sliceName, reducer);
So basically every page would have a globalsSlice, containing the user info and some other global data, and Redux Toolkit Query API slice (which would then be code-split using RTKQ injectEndpoints functionality).
With this setup, each page that wants to inject its own custom slice (reducer) would do something like this:
const SomePage = () => {
const someData = useSelector(somePageSliceSelectors.selectSomeData);
return (
<Fragment>
<Head>
<title>Some Page</title>
</Head>
</Fragment>
)
};
export default SomeRoute;
injectReducer('somePageSlice', somePageReducer);
export const getServerSideProps = wrapper.getServerSideProps((store) => async (context) => {
// Whatever necessary logic we need
});
Initially this seemed to have worked fine, but then when I realized that next-redux-wrapper works by calling the makeStore factory on every request, and I'm manipulating and mutating a global store object, there has to be something wrong with this, ie a race condition that I haven't been able to cause by testing. Also another problem occurres when using Redux Toolkit Query. For example, if I need to get a cookie from the original request (the one that nextjs receives) and then re-send it to another API endpoint that is handled by redux toolkit query, I would need to extract the cookie from the request context, to which I don't have access unless I do something like this:
export const makeStore = (ctx) => {
return configureStore({
reducer: ...,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
thunk: {
extraArgument: ctx,
},
}).concat(...),
});
};
which further implies that I should definitely not be mutating the global store object.
So then I thought alright, instead of manipulating the global store I could try doing it in GSSP:
export const getServerSideProps = wrapper.getServerSideProps((store) => async (context) => {
store.injectDynamicReducer('somePageSlice', somePageReducer);
});
But no luck here, the slice does not get loaded and the state does not get constructed. It is my guess that the Provider in the _app gets rendered before this, but I'm not sure.
In conclusion, I'd like to know whether anyone has tried and succeeded in implementing redux code splitting using RTK, RTKQ and NextJs. Also, I would like to ask an addition question: Is it necessary? What I mean by this is, if I were to not code-split at all, and send all slices on every request, how performance impactful would this be? Also, since I'm not sure exactly how the NextJs bundler works and how code chunking is done: If a certain page receives a slice it doesn't use at all, will it only receive its initial state or all of its logic (all the selectors, reducers and actions)? If not then maybe this isn't so bad, since initial states are just empty objects.
I hope I've presented the problem clearly enough, as it is a very complex problem, but feel free to ask follow up questions if something doesn't make sense.
Thanks in advance.

In redux, why are action types defined first as a constant rather than being named directly in the function?

I'm new to front-end development, so maybe someone could kindly clarify the following:
In Redux, I see in all the video tutorials that actions are defined like so:
const SOME_ACTION = "SOME_ACTION"
export const someAction = () => ({
type: SOME_ACTION
})
I wonder, what's the point of defining the SOME_ACTION constant?
Why not just skip it and name the action in the function itself? For instance:
export const someAction = () => ({
type: "SOME_ACTION"
})
What are we gaining by having a global variable that is only used within a function by the same name?
Many thanks!

Firestore data won't load until I change code file on React Native App

This might sound weird but my Firestore data won't display on my app unless I save my code files.
Here is my screen when I get to the screen for the first time. Also, the items under Today's Deals are hard-coded.
Then here is my screen when I save my merchant.js file in vscode.
const store = route.params;
const [items, setItems]=useState([])
let storeItems;
const getStoreItems = async()=>{
let merchantId_str = String(store.merchantId);
const response = firestore().collection('Items').where('merchantId', '==', merchantId_str)
const data = await response.get();
data.docs.forEach(item=>{
items.push(item.data());
})
}
storeItems = getUniqueListBy(items, 'sukiId');
storeCategs = getUniqueListByCateg(items, 'storeCateg');
useEffect(() => {
getStoreItems();
}, [])
I've tried to console.log(Items) as well when nothing loads and it's empty.
It seems that you are trying to modify the read-only state of items at
items.push(item.data());
Use the provided setItems function instead. Something like this should work:
let receivedData = [];
data.docs.forEach(item=>{
receivedData.push(item.data());
})
setItems(receivedData);
You should be receiving some sort of a warning message in the console though about this.
I believe your usecase is not suitable for "useEffect" hook.
What does useEffect do? By using this Hook, you tell React that your component needs to do something after render.
You may explore on "useState".
useState is a Hook that lets you add React state to function components.
Read more about useState and useEffect on the official React docs.

What is a difference between mapStateToProps,mapDispatchToProps types and selector in reactnative

I am new to react native with redux. I am trying to figure out how all the pieces in react-native redux integration. The one thing giving me trouble is understanding the difference types and selector give me more details.
MapStateToProps -> has his name say, you can map state objects to props. Example:
You have a store like this:
{
name:'paul',
surname:'watson'
}
Then you need show in your component the name, so in your container you can access to this data stored in store with mapstatetoprops, like this:
const mapStateToProps = (state, ownProps) => ({
myname: state.name,
})
MapDispatchToProps -> thats when you need dispatch an action, you map an action to a prop to you can use in your component
You have an action like:
const setMyName = payload => ({
type: SET_MY_NAME,
payload,
})
then you need update your name in store when user click something throw this action, so you can map this action in a prop to call like updateName('pepito') with mapDispatchToProps, like this:
const mapDispatchToProps = {
updateName: setMyName,
}
Selectors -> it's just an abstraction code, selectors make your life more easy.
Selectors are functions that take Redux state as an argument and return some data to pass to the component, like this:
const getDataType = state => state.editor.dataType;
Thats a basic concepts, you should read oficial document and search, in internet have a lot of articles about this.

Why the reselect createSelector necessary in this #ngrx example?

What does the following code snippet do? It is taken from this file.
export const getCollectionLoading = createSelector(getCollectionState, fromCollection.getLoading);
The fromCollection.getLoading has only either true or false value, so can there be any optimization achieved by using the createSelector?
in
export const getCollectionLoaded = createSelector(getCollectionState, fromCollection.getLoaded);
export const getCollectionLoading = createSelector(getCollectionState, fromCollection.getLoading);
export const getCollectionBookIds = createSelector(getCollectionState, fromCollection.getIds);
According to the example app's comments:
/**
* Every reducer module exports selector functions, however child reducers
* have no knowledge of the overall state tree. To make them useable, we
* need to make new selectors that wrap them.
**/
For example in reducers/collections.ts the selectors at the bottom of the file only reference the collection slice:
export const getLoaded = (state: State) => state.loaded;
export const getLoading = (state: State) => state.loading;
export const getIds = (state: State) => state.ids;
These collection selectors can't be used with state.select() because state.select expects to work with the whole AppState. Therefore in the reducers/index.ts the selector is then wrapped with another selector so that it does work with the whole AppState:
export const getCollectionLoading = createSelector(getCollectionState, fromCollection.getLoading);
Back to your question: why is it necessary to use reselect for this. Reselect in this case isn't providing any optimizations. So the main purpose of reselect is that it provides the ability to compose selectors together.
By using this composition feature we can make collections.ts only have selectors for the collections slice. Then in index.ts we can have selectors at the AppState level. Furthermore we can have selectors that work across different slices of the store such as this one:
/**
* Some selector functions create joins across parts of state. This selector
* composes the search result IDs to return an array of books in the store.
*/
export const getSearchResults = createSelector(getBookEntities,
getSearchBookIds, (books, searchIds) => {
return searchIds.map(id => books[id]);
});
Yes, there may be performance gains. If fromCollection.getLoading computation is expensive, reselect would avoid useless recalculations until getCollectionState keeps returning the same value.

Resources