How to delete a redux store by key name - redux

I have configured my main store in redux persist like this:
const persistConfig = {
key: 'v1.0',
storage: AsyncStorage,
};
Now I have changed the store key name, as I found out I can use version instead to version my store and structure.
It became this:
const persistConfig = {
key: 'root',
version: 2,
storage: AsyncStorage,
migrate: createMigrate(migrations, { debug: false }),
};
My problem is that the previous store key: 'v1.0' is still available and I can access it if I change the key name back to it. How can I clear all data on that store and just remove it?

This is the method I found until now that seem to work.
Assign the old store before the new one and use the method Purge().
/***** OLD STORE PURGING ******/
const persistConfigOld = {
key: 'v1.0',
storage: AsyncStorage,
};
const persistedReducerOld = persistReducer(persistConfigOld, rootReducer)
const oldStore = createStore(
persistedReducerOld,
);
//purge
const purge = (store) => {
return new Promise(
(resolve, reject) => {
// Purge RAM cached reducer states
store.dispatch({ type: "RESET" });
// Purge disk cached reducer states
const persistor = persistStore(store, {},
(err) => {
if (err)
reject(err);
resolve();
}
);
persistor.purge();
}
);
};
purge(oldStore);
/***** END OLD STORE PURGING ******/
Found here.

Related

graphql/apollo persistent queries are too long(http 414)

I'm currently working on a site wgich has a frontend consisting of next.js which communicates over graphql to a WordPress backend. the persistent queries are generated(by graphql-codegen) and are saved to a .json files both the backend and frontend can access these files.
here is the code relating to apollo and apollo codegen
codegen.js
const environment = process.env.ENV || 'development';
const url = require(`./config/${environment}`);
module.exports = {
schema: `${url.backend}/graphql`,
documents: ['./lib/queries/fragments/*.js', './lib/queries/*.js'],
generates: {
'./lib/persisted-query-ids/client.json': [
{
'graphql-codegen-persisted-query-ids': {
output: 'client',
algorithm: 'sha256',
preset: 'near-operation-file',
},
},
],
'./lib/persisted-query-ids/server.json': [
{
'graphql-codegen-persisted-query-ids': {
output: 'server',
algorithm: 'sha256',
preset: 'near-operation-file',
},
},
],
},
};
createApolloClient.js
export default function createApolloClient(initialState, ctx) {
const hashes = require('../../persisted-query-ids/client.json');
const persistedLink = createPersistedQueryLink({
useGETForHashedQueries: true, // Optional but allows better caching
// eslint-disable-next-line react-hooks/rules-of-hooks
generateHash: usePregeneratedHashes(hashes),
});
// The `ctx` (NextPageContext) will only be present on the server.
// use it to extract auth headers (ctx.req) or similar.
const fetchOptions = {
// credentials: 'include',
redirect: 'manual',
};
const fetchWithCookies = async (input, init) => {
let isomorphicFetch;
if (typeof window === 'undefined') {
isomorphicFetch = (await import('isomorphic-unfetch')).default;
} else {
isomorphicFetch = window.fetch;
}
const result = await isomorphicFetch(input, init);
if (ctx?.res) {
const cookiesFromApi = result.headers.get('set-cookie');
if (cookiesFromApi) {
ctx?.res.setHeader('set-cookie', cookiesFromApi);
}
}
return result;
};
const cookieLink = createCookieLink(ctx);
const httpLink = persistedLink.concat(
new HttpLink({
uri: `${config.wordpress.backend}/graphql`,
fetchOptions,
fetch: fetchWithCookies,
useGETForQueries: true,
})
);
return new ApolloClient({
ssrMode: typeof window === 'undefined',
link: cookieLink.concat(httpLink),
cache: new InMemoryCache().restore(initialState || {}),
});
}
this is the URL of the request, as you can see its quite big. the problem is apollo wants to use the query and not the persisted query id. this request causes a http 414 code. one of the fixes is to make another query for the fragments
https://example.com/wp/graphql?query=query%20GetFrontPage%20%7B%0A%20%20page%3A%20pageOnFront%20%7B%0A%20%20%20%20nodes%20%7B%0A%20%20%20%20%20%20...PageData%0A%20%20%20%20%20%20__typename%0A%20%20%20%20%7D%0A%20%20%20%20__typename%0A%20%20%7D%0A%7D%0A%0Afragment%20PageData%20on%20Page%20%7B%0A%20%20title%0A%20%20content%0A%20%20link%0A%20%20excerpt%0A%20%20pageTemplate%0A%20%20hero%20%7B%0A%20%20%20%20heroColor%0A%20%20%20%20heroImage%20%7B%0A%20%20%20%20%20%20sourceUrl%0A%20%20%20%20%20%20altText%0A%20%20%20%20%20%20__typename%0A%20%20%20%20%7D%0A%20%20%20%20heroTitle%0A%20%20%20%20heroTitleTop%0A%20%20%20%20heroDescription%0A%20%20%20%20__typename%0A%20%20%7D%0A%20%20featuredImage%20%7B%0A%20%20%20%20...FeaturedImage%0A%20%20%20%20__typename%0A%20%20%7D%0A%20%20seo%20%7B%0A%20%20%20%20...Seo%0A%20%20%20%20__typename%0A%20%20%7D%0A%20%20...FlexContentPage%0A%20%20__typename%0A%7D%0A%0Afragment%20Seo%20on%20PostTypeSEO%20%7B%0A%20%20title%0A%20%20metaDesc%0A%20%20metaKeywords%0A%20%20metaRobotsNofollow%0A%20%20metaRobotsNoindex%0A%20%20canonical%0A%20%20opengraphTitle%0A%20%20opengraphDescription%0A%20%20opengraphImage%20%7B%0A%20%20%20%20sourceUrl(size%3A%20FEATIMGSOCIAL)%0A%20%20%20%20__typename%0A%20%20%7D%0A%20%20twitterTitle%0A%20%20twitterDescription%0A%20%20twitterImage%20%7B%0A%20%20%20%20sourceUrl(size%3A%20FEATIMGSOCIAL)%0A%20%20%20%20__typename%0A%20%20%7D%0A%20%20__typename%0A%7D%0A%0Afragment%20FlexContentPage%20on%20Page%20%7B%0A%20%20flexContent%20%7B%0A%20%20%20%20flexiblecontent%20%7B%0A%20%20%20%20%20%20...%20on%20Page_Flexcontent_Flexiblecontent_SellingPoints%20%7B%0A%20%20%20%20%20%20%20%20fieldGroupName%0A%20%20%20%20%20%20%20%20title%0A%20%20%20%20%20%20%20%20subtitle%0A%20%20%20%20%20%20%20%20sellingpointsBackgroundColor%0A%20%20%20%20%20%20%20%20cta%20%7B%0A%20%20%20%20%20%20%20%20%20%20target%0A%20%20%20%20%20%20%20%20%20%20title%0A%20%20%20%20%20%20%20%20%20%20url%0A%20%20%20%20%20%20%20%20%20%20__typename%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20list%20%7B%0A%20%20%20%20%20%20%20%20%20%20listTitle%0A%20%20%20%20%20%20%20%20%20%20pointsList%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20point%0A%20%20%20%20%20%20%20%20%20%20%20%20__typename%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20__typename%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20__typename%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20...%20on%20Page_Flexcontent_Flexiblecontent_Titlelayout%20%7B%0A%20%20%20%20%20%20%20%20fieldGroupName%0A%20%20%20%20%20%20%20%20titleBackgroundcolor%0A%20%20%20%20%20%20%20%20titles%20%7B%0A%20%20%20%20%20%20%20%20%20%20fieldGroupName%0A%20%20%20%20%20%20%20%20%20%20titleTitle%0A%20%20%20%20%20%20%20%20%20%20titleTitleColor%0A%20%20%20%20%20%20%20%20%20%20__typename%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20__typename%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20...%20on%20Page_Flexcontent_Flexiblecontent_Testemonial%20%7B%0A%20%20%20%20%20%20%20%20fieldGroupName%0A%20%20%20%20%20%20%20%20title%0A%20%20%20%20%20%20%20%20testemonial%0A%20%20%20%20%20%20%20%20facts%20%7B%0A%20%20%20%20%20%20%20%20%20%20factCount%0A%20%20%20%20%20%20%20%20%20%20fieldGroupName%0A%20%20%20%20%20%20%20%20%20%20factTitle%0A%20%20%20%20%20%20%20%20%20%20__typename%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20__typename%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20...%20on%20Page_Flexcontent_Flexiblecontent_Pointslayout%20%7B%0A%20%20%20%20%20%20%20%20fieldGroupName%0A%20%20%20%20%20%20%20%20title%0A%20%20%20%20%20%20%20%20points%20%7B%0A%20%20%20%20%20%20%20%20%20%20itemdescription%0A%20%20%20%20%20%20%20%20%20%20itemtitle%0A%20%20%20%20%20%20%20%20%20%20__typename%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20__typename%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20...%20on%20Page_Flexcontent_Flexiblecontent_Bloglayout%20%7B%0A%20%20%20%20%20%20%20%20fieldGroupName%0A%20%20%20%20%20%20%20%20blogSubtitle%0A%20%20%20%20%20%20%20%20blogCta%20%7B%0A%20%20%20%20%20%20%20%20%20%20target%0A%20%20%20%20%20%20%20%20%20%20title%0A%20%20%20%20%20%20%20%20%20%20url%0A%20%20%20%20%20%20%20%20%20%20__typename%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20blogCases%20%7B%0A%20%20%20%20%20%20%20%20%20%20...%20on%20Post%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20title%0A%20%20%20%20%20%20%20%20%20%20%20%20uri%0A%20%20%20%20%20%20%20%20%20%20%20%20details%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20broad%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20sourceUrl%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20altText%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20__typename%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20customer%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20normal%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20sourceUrl%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20altText%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20__typename%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20small%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20sourceUrl%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20altText%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20__typename%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20subtitle%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20video%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20mediaItemUrl%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20altText%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20__typename%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20__typename%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20slug%0A%20%20%20%20%20%20%20%20%20%20%20%20featuredImage%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20node%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20sourceUrl%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20altText%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20__typename%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20__typename%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20__typename%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20__typename%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20blogTitle%0A%20%20%20%20%20%20%20%20blogColor%0A%20%20%20%20%20%20%20%20blogSubtitle%0A%20%20%20%20%20%20%20%20__typename%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20...%20on%20Page_Flexcontent_Flexiblecontent_Latestlayout%20%7B%0A%20%20%20%20%20%20%20%20fieldGroupName%0A%20%20%20%20%20%20%20%20latestTitle%0A%20%20%20%20%20%20%20%20__typename%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20...%20on%20Page_Flexcontent_Flexiblecontent_Testlayout%20%7B%0A%20%20%20%20%20%20%20%20fieldGroupName%0A%20%20%20%20%20%20%20%20testTitle%0A%20%20%20%20%20%20%20%20__typename%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20...%20on%20Page_Flexcontent_Flexiblecontent_Textlayout%20%7B%0A%20%20%20%20%20%20%20%20fieldGroupName%0A%20%20%20%20%20%20%20%20wysiwyg%0A%20%20%20%20%20%20%20%20backgroundcolor%0A%20%20%20%20%20%20%20%20__typename%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20...%20on%20Page_Flexcontent_Flexiblecontent_Gallerylayout%20%7B%0A%20%20%20%20%20%20%20%20fieldGroupName%0A%20%20%20%20%20%20%20%20photos%20%7B%0A%20%20%20%20%20%20%20%20%20%20fieldGroupName%0A%20%20%20%20%20%20%20%20%20%20pullup%0A%20%20%20%20%20%20%20%20%20%20photo%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20sourceUrl%0A%20%20%20%20%20%20%20%20%20%20%20%20altText%0A%20%20%20%20%20%20%20%20%20%20%20%20__typename%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20__typename%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20__typename%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20...%20on%20Page_Flexcontent_Flexiblecontent_Visuallayout%20%7B%0A%20%20%20%20%20%20%20%20fieldGroupName%0A%20%20%20%20%20%20%20%20image%20%7B%0A%20%20%20%20%20%20%20%20%20%20sourceUrl%0A%20%20%20%20%20%20%20%20%20%20altText%0A%20%20%20%20%20%20%20%20%20%20__typename%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20__typename%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20...%20on%20Page_Flexcontent_Flexiblecontent_Customerslayout%20%7B%0A%20%20%20%20%20%20%20%20__typename%0A%20%20%20%20%20%20%20%20fieldGroupName%0A%20%20%20%20%20%20%20%20backgroundColor%0A%20%20%20%20%20%20%20%20title%0A%20%20%20%20%20%20%20%20subtitle%0A%20%20%20%20%20%20%20%20customers%20%7B%0A%20%20%20%20%20%20%20%20%20%20link%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20target%0A%20%20%20%20%20%20%20%20%20%20%20%20title%0A%20%20%20%20%20%20%20%20%20%20%20%20url%0A%20%20%20%20%20%20%20%20%20%20%20%20__typename%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20logo%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20sourceUrl%0A%20%20%20%20%20%20%20%20%20%20%20%20altText%0A%20%20%20%20%20%20%20%20%20%20%20%20__typename%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20__typename%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20...%20on%20Page_Flexcontent_Flexiblecontent_Slidelayout%20%7B%0A%20%20%20%20%20%20%20%20__typename%0A%20%20%20%20%20%20%20%20fieldGroupName%0A%20%20%20%20%20%20%20%20ctaLink%20%7B%0A%20%20%20%20%20%20%20%20%20%20target%0A%20%20%20%20%20%20%20%20%20%20title%0A%20%20%20%20%20%20%20%20%20%20url%0A%20%20%20%20%20%20%20%20%20%20__typename%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20slideBigTitle%0A%20%20%20%20%20%20%20%20slideBigDescription%0A%20%20%20%20%20%20%20%20slideContent%20%7B%0A%20%20%20%20%20%20%20%20%20%20slideImage%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20sourceUrl%0A%20%20%20%20%20%20%20%20%20%20%20%20altText%0A%20%20%20%20%20%20%20%20%20%20%20%20__typename%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20slideColor%0A%20%20%20%20%20%20%20%20%20%20slideTitle%0A%20%20%20%20%20%20%20%20%20%20slideDescription%0A%20%20%20%20%20%20%20%20%20%20__typename%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20...%20on%20Page_Flexcontent_Flexiblecontent_Teamlayout%20%7B%0A%20%20%20%20%20%20%20%20__typename%0A%20%20%20%20%20%20%20%20fieldGroupName%0A%20%20%20%20%20%20%20%20teamContent%20%7B%0A%20%20%20%20%20%20%20%20%20%20fieldGroupName%0A%20%20%20%20%20%20%20%20%20%20teamMemberName%0A%20%20%20%20%20%20%20%20%20%20teamMemberRole%0A%20%20%20%20%20%20%20%20%20%20__typename%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20teamBigTitle%0A%20%20%20%20%20%20%20%20teamBigSubtitle%0A%20%20%20%20%20%20%20%20teamContent%20%7B%0A%20%20%20%20%20%20%20%20%20%20teamMemberName%0A%20%20%20%20%20%20%20%20%20%20teamMemberRole%0A%20%20%20%20%20%20%20%20%20%20teamMemberImage%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20sourceUrl%0A%20%20%20%20%20%20%20%20%20%20%20%20altText%0A%20%20%20%20%20%20%20%20%20%20%20%20__typename%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20__typename%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20...%20on%20Page_Flexcontent_Flexiblecontent_Awardslayout%20%7B%0A%20%20%20%20%20%20%20%20fieldGroupName%0A%20%20%20%20%20%20%20%20awardsTitle%0A%20%20%20%20%20%20%20%20awardsBackgroundColor%0A%20%20%20%20%20%20%20%20awardsSubtitle%0A%20%20%20%20%20%20%20%20awards%20%7B%0A%20%20%20%20%20%20%20%20%20%20awardLink%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20target%0A%20%20%20%20%20%20%20%20%20%20%20%20title%0A%20%20%20%20%20%20%20%20%20%20%20%20url%0A%20%20%20%20%20%20%20%20%20%20%20%20__typename%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20awardLogo%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20sourceUrl%0A%20%20%20%20%20%20%20%20%20%20%20%20altText%0A%20%20%20%20%20%20%20%20%20%20%20%20__typename%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20awardImage%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20sourceUrl%0A%20%20%20%20%20%20%20%20%20%20%20%20altText%0A%20%20%20%20%20%20%20%20%20%20%20%20__typename%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20awardPrize%0A%20%20%20%20%20%20%20%20%20%20awardProject%0A%20%20%20%20%20%20%20%20%20%20awardOrganisation%0A%20%20%20%20%20%20%20%20%20%20__typename%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20__typename%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20...%20on%20Page_Flexcontent_Flexiblecontent_Accordionlayout%20%7B%0A%20%20%20%20%20%20%20%20__typename%0A%20%20%20%20%20%20%20%20fieldGroupName%0A%20%20%20%20%20%20%20%20accordionBackgroundColor%0A%20%20%20%20%20%20%20%20accordionItems%20%7B%0A%20%20%20%20%20%20%20%20%20%20accordionTitle%0A%20%20%20%20%20%20%20%20%20%20accordionContent%0A%20%20%20%20%20%20%20%20%20%20accordionServices%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20accordionService%0A%20%20%20%20%20%20%20%20%20%20%20%20__typename%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20__typename%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20__typename%0A%20%20%20%20%7D%0A%20%20%20%20__typename%0A%20%20%7D%0A%20%20__typename%0A%7D%0A%0Afragment%20FeaturedImage%20on%20NodeWithFeaturedImageToMediaItemConnectionEdge%20%7B%0A%20%20node%20%7B%0A%20%20%20%20link%0A%20%20%20%20sourceUrl(size%3A%20FEATIMGSOCIAL)%0A%20%20%20%20altText%0A%20%20%20%20title%0A%20%20%20%20mediaDetails%20%7B%0A%20%20%20%20%20%20width%0A%20%20%20%20%20%20height%0A%20%20%20%20%20%20__typename%0A%20%20%20%20%7D%0A%20%20%20%20__typename%0A%20%20%7D%0A%20%20__typename%0A%7D&operationName=GetFrontPage&variables=%7B%7D&extensions=%7B%22persistedQuery%22%3A%7B%22version%22%3A1%2C%22sha256Hash%22%3A%22e429ca4a5a03ff00fd8e895c639f032e66a3b212ced449b733d8a38693458419%22%7D%7D
What I want is that apollo automatically uses queryId as seen on but I just can't figure out what could lead to a solution. if you have any suggestions I would love to hear them.
it looks like the only solution is to split up the query into multible parts

How to update or change the entire propery of a particular redux object

Am having issues updating a redux store in NEXTJS. am building a CV platform with the feature to preview users' input almost immediately into a preview page. this cv platform has the experience, education etc that a normal cv platform should have and am using the react hook form package to manage forms and also to enhance dynamic forms.
so because the preview component will be another project on its own, I need the best way to pass data from my app into the preview app. Then I thought of passing every form input, cv styles, and data to a redux store so the preview component can just get the user's data from the store
as I said earlier, am using the react hooks form library to manage my form, so to update the store in real-time whenever the user inputs anything, I imported the useWatch hook from react hook form to watch my form in case of any data changes. so I set up a useEffect to listen for any useWatch change to dispatch the whole useWatch data to the store. NB: this data contains an array of objects
my challenge right now is that anytime I dispatch the data to store, redux toolkit or probably immer frowns at what am doing and will always break the app, returning back this error message
TypeError: Cannot assign to read only property 'jobTitle' of object '#<Object>'
at set (index.esm.mjs?b902:507:1)
at onChange (index.esm.mjs?b902:1749:1)
at HTMLUnknownElement.callCallback (react-dom.development.js?ac89:4164:1)
at Object.invokeGuardedCallbackDev (react-dom.development.js?ac89:4213:1)
at invokeGuardedCallback (react-dom.development.js?ac89:4277:1)
at invokeGuardedCallbackAndCatchFirstError (react-dom.development.js?ac89:4291:1)
at executeDispatch (react-dom.development.js?ac89:9041:1)
at processDispatchQueueItemsInOrder (react-dom.development.js?ac89:9073:1)
at processDispatchQueue (react-dom.development.js?ac89:9086:1)
at dispatchEventsForPlugins (react-dom.development.js?ac89:9097:1)
at eval (react-dom.development.js?ac89:9288:1)
at batchedUpdates$1 (react-dom.development.js?ac89:26140:1)
at batchedUpdates (react-dom.development.js?ac89:3991:1)
at dispatchEventForPluginEventSystem (react-dom.development.js?ac89:9287:1)
at dispatchEventWithEnableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay (react-dom.development.js?ac89:6465:1)
at dispatchEvent (react-dom.development.js?ac89:6457:1)
at dispatchDiscreteEvent (react-dom.development.js?ac89:6430:1)
Below is the redux store and how am setting the experience
const initialState: IResume = {
templatePrimaryColor: "#335384",
top: 0,
showOverlay: false,
cv_object: {
templateId: 1,
personalInformation: {} as PersonalInformation,
experiences: [] as Experience[],
educations: [] as Education[],
skills: [] as Skill[],
awards: [] as Award[],
certificates: [] as Certificate[],
publications: [] as Publication[],
references: [] as Reference[],
},
};
export const resumeSlice = createSlice({
name: "resume",
initialState,
reducers: {
setExperience: (state, action: PayloadAction<Experience[]>) => {
// state.cv_object.experiences = [...action.payload];
state.cv_object.experiences = Object.assign(state.cv_object.experiences, action.payload);
},
},
});
Below is how am setting the forms and how am dispatching it
//React hooks form initialSetup
const { register, control, handleSubmit } = useForm<CvObject>({
defaultValues: {
experiences: [{ ...ExperienceDefaultValues }],
},
});
//usefieldArray for dynamic forms
const { append, fields, remove } = useFieldArray({ control, name: "experiences" });
//dispatch the entire form data to experience if any changes is being made
const formValues = useWatch({ control, name: "experiences" });
const [currentFormIndex, setCurrentFormIndex] = useState(0);
useEffect(() => {
if (!useAi) dispatch(hideOverlay());
else dispatch(showOverlay());
}, [useAi]);
useEffect(() => {
dispatch(setExperience(formValues));
}, [formValues]);
const handleAddAnotherExperience = () => {
setCurrentFormIndex((prev) => prev + 1);
append({ ...ExperienceDefaultValues });
};
const handleDelete = (index: number) => {
remove(index);
if (currentFormIndex > 0) setCurrentFormIndex((prev) => prev - 1);
};
const handleEdit = (index: number) => {
setCurrentFormIndex(index);
};
This is the sample object of the experience am passing but Array of Experience
export interface Experience {
companyName: string;
fromYear: string;
toYear: string;
fromMonth: string;
toMonth: string;
currentlyWorking: boolean;
achievements: string;
description: string;
city: string;
country: string;
index: number;
jobTitle: string;
}
So what am really expecting from this is how to change the store or how to replace the previous experience that is in the store with the incoming experience that is being dispatched.
React hook form is the guy handling new object, removing new object with their useFieldArray hooks.
First of all, you shouldn't directly mutate the data in the redux store, so you can use the object spread operator to create new objects and secondly you should always have a return statement in your slice. So your resumeslice should actually be like this
export const resumeSlice = createSlice({
name: "resume",
initialState,
reducers: {
setExperience: (state, action: PayloadAction<Experience[]>) => {
state = {
...state,
cv_object: {
...state.cv_object,
experiences: action.payload
}
}
return state
},
},
});
I believe this should work

Why redux store doesn't receive an update from immer

Combining reducers
export default (injectedReducers = {}) => {
return combineReducers({
...injectedReducers,
memoizedStamps: memoizedStampsReducer, // <-- need to write here
});
};
Writing an action
const mapDispatch = (dispatch) => ({
addStamp: (payload) =>
dispatch({
type: ADD_STAMP,
payload,
}),
});
Writing the reducer
export const initialState = [];
const memoizedStampsReducer = produce((draft, action) => {
const { type, payload } = action;
switch (type) {
case ADD_STAMP:
draft.push(payload);
}
}, initialState);
export default memoizedStampsReducer;
Using in a react hook
const useMemoizedStamps = () => {
const [memStamps, dispatch] = useImmerReducer(reducer, initialState);
const { addStamp } = mapDispatch(dispatch);
useEffect(() => {
addStamp({ body: 'body', coords: 'coords' });
}, []);
console.log(memStamps); // <-- gives [{ body: 'body', coords: 'coords' }] all good here
return null;
};
export default useMemoizedStamps;
But it gets never saved into injected reducer "memoizedStamps". The array is always empty. It works perfectly will with connect(null, mapDispatchToProps), but can't use connect() in my custom hook.
What do I do wrong? What is the answer here?
--- UPD 1 ---
#phry, like so?
const useMemoizedStamps = (response = null, error = null) => {
const dispatch = useDispatch();
const [memStamps] = useImmerReducer(reducer, initialState);
const { addStamp } = mapDispatch(dispatch);
useEffect(() => {
addStamp({ body: 'body', coords: 'coords' });
}, []);
console.log(memStamps);
return null;
};
And now if I need them to be local, I need to use immer's dispatcher? Any way to merge these two dispatchers? P.S. this dispatcher really saved it to global state.
Rereading this, I think you just have a misconception.
Stuff is never "saved into a reducer". A reducer only manages how state changes.
In Redux, it would be "saved into the store", but for that you would have to actually use a store. useImmerReducer has nothing to do with Redux though - it is just a version of useReducer, which like useState just manages isolated component-local state with a reducer. This state will not be shared with other components.
If you want to use Redux (and use it with immer), please look into the official Redux Toolkit, which already comes with immer integrated. It is taught by the official Redux tutorial.

How to join data from two collections by reference field in Firestore?

I have 2 collections in my firestore. One called owners and the second is unicorns.
An owner has only a name field and a unicorn has a name and a reference to the owner.
I want a query to return an array of objects that looks like this
unicorns = { id: 123,
name: Dreamy,
owner: { id: 1
name: John Cane
}
}
my query looks like this but there is something missing that I can't figure out
let unis = [];
db
.collection("unicorns")
.get()
.then((querySnapshot) => {
querySnapshot.forEach((doc) => {
let uni = {
id: doc.id,
name: doc.data().name,
owner: doc.data().owner,
};
if (uni.owner) {
doc
.data()
.owner.get()
.then((res) => {
uni.owner = {
id: res.id,
name: res.data().name,
};
unis.push(uni);
})
.then(() => {
setUnicorns(unis);
})
.catch((err) => console.error(err));
} else {
unis.push(uni);
}
});
})
When I setUnicorns hook and I try to map the results I don't get all the data I need
You cannot run the .get() method on a string. You would have to run a separate request to firestore to get owner documents. I would recommend using a for-of inside a async function as shown below.
const db = admin.firestore()
//Declare the reference for collections before the loop starts
const ownersCollection = db.collection("owners")
const unicornsCollection = db.collection("unicorns")
const ownersData = {}
let unis = [];
unicornsCollection.get().then(async (querySnapshot) => {
for (const doc of querySnapshot) {
let uni = {
id: doc.id,
name: doc.data().name,
//Assuming the owner field is the UID of owner
owner: doc.data().owner,
};
if (uni.owner) {
//Check if owner's data is already fetched to save extra requests to Firestore
if (ownersData[uni.owner]) {
uni.owner = {
id: ownersData[uni.owner].id,
name: ownersData[uni.owner].name,
};
unis.push(uni);
} else {
//User the ownersCollection Reference to get owner information
ownersCollection.doc(uni.owner).get().then((ownerDoc) => {
uni.owner = {
id: ownerDoc.data().id,
name: ownerDoc.data().name,
};
ownersData[uni.owner] = {
id: ownerDoc.data().id,
name: ownerDoc.data().name,
}
unis.push(uni);
}).then(() => {
setUnicorns(unis);
}).catch((err) => console.error(err));
}
} else {
unis.push(uni);
}
}
})
How this works? It fetches all the unicorn documents and iterates over then to check if the document has owner's UID. If yes then runs another request to Firestore to get that unicorn's owner's document. Let me know if you have any questions.
Edit: In case a single owner has multiple unicorns then you surely don't want to fetch the data of same owner again and again. So add that in an object locally and check if the data of that owner is already fetched before making a request to Firestore. Code for the same updated above.

Vuex and Firebase, store additional user info

I have a function where i'm creating a user with Firebase and Vuex, and want to store some additional information about the user.
When I create a user, I run the code below, where payload contains email, password and name as an object.
This is in actions in vuex.
signUserUp ({ commit }, payload) {
firebase.auth().createUserWithEmailAndPassword(payload.email, payload.password)
.then((u) => {
firebase.database().ref('users/' + u.user.uid).set({
name: payload.name,
email: payload.email,
registeredTools: []
})
// This commit('setUser')... sets the local data (local state).
commit('setUser', { id: u.user.uid, name: payload.name, email: payload.email, registeredTools: [] })
})
.catch(
error => {
console.log(error)
}
)
},
The user gets created, and my database store data like name and email, (I will soon be adding some new datafields to the user. )
This workes as expected. I have an autoSignIn-function which updates the local user when refreshing or closing/opening the browser. My problem occurs when i'm getting the userdata, and try to merge the object from the auth-function (only ID and email), with the the object from my database, which currently, only holds the name of the user.
-Here is my attempt:
autoSignIn ({ commit }, payload) {
const userDataFromAuth = { id: payload.uid, email: payload.email }
firebase.database().ref('users/' + payload.uid).once('value')
.then((data) => {
const userDataFromDatabase = []
const obj = data.val()
for (let key in obj) {
userDataFromDatabase.push({
name: obj[key].name
})
}
var userData = {...userDataFromAuth, ...userDataFromDatabase}
console.log(userData)
commit('setUser', userData)
})
},
Any ideas on how I might do this?
This is a pretty good solution to the problem:
autoSignIn ({ commit }, payload) {
const userDataFromAuth = { id: payload.uid, email: payload.email }
firebase.database().ref('users/' + payload.uid).once('value')
.then((data) => {
const userDataFromDatabase = { name: data.child('name').val() }
const userData = { ...userDataFromAuth, ...userDataFromDatabase }
commit('setUser', userData)
})
},
First, we get the data from the auth-function of firebase (which contains id and email). And then we get the data under 'users/' + payload.uid (id), and then we merge those two javascript objects, and store them in the store.users (vuex's local store of data), which we can use throughout our application. Please feel free to ask questions or suggestions for improvements.

Resources