How to use manual cache updates using RTK Query - javascript

I have recently started working on redux toolkit, Basically i want to refetch the data from database if there is mutation. I am using flatlist in my react native project where on pull to refresh i want my "getPosts" endpoint to refetch and get updated.
Note: I know about using tags for automated cache invalidation. but on web RTK query is not implemented.
Talking about pessimistic update:
async onQueryStarted({ id, ...patch }, { dispatch, queryFulfilled }) {
try {
const { data: updatedPost } = await queryF`enter code here`ulfilled
const patchResult = dispatch(
api.util.updateQueryData('getPost', id, (draft) => {
Object.assign(draft, updatedPost)
})
)
} catch {}
},
just give a help how to call this function from APP.JS or anywhere from the app. Thanks

You can just call refetch, you don't need anything that complicated. See the docs on useQuery
const myResult = useMyquery(args)
// in your pull to refresh trigger:
myResult.refetch()
If you are outside of a component, you can also still
store.dispatch(api.endpoints.myEndpoint.initiate(args, { track: false })))
to trigger a refetch

Related

NextJS: Do I need to use getInitialProps with next-redux-wrapper to share state to all pages?

I'm using next-redux-wrapper and dispatching actions from getServerSideProps from individual pages. But I realized that I can't access the populated store state from another page. If I try to, in either client-side or server-side, the state returns empty in the other pages.
So, I heard that using getInitialProps is required to share state among all pages. Since I'm getting confused with all these I want to have some doubts cleared. I want to know:
When is it necessary, if at all, to use getInitialProps in the _app.js file when using redux with next-redux-wrapper? I heard that need to use getInitialProps inside _app.js in order to make the state accessible to every pages. But it's not working for me. Maybe due to wrong implementation!
If I use getInitialProps in _app.js then, is it not required to use getServerSideProps or getStaticProps in individual pages?
After populating state with getServerSideProps, can I share the state to every page without using getInitialProps in _app.js or if nneded can I pass the fetched state to getInitialProps in _app.js?
Yes, You have to use getIntitprops in the APP component to provide store in all pages in this case all page will run on a server which huge downfall, if you have lots of static pages,
or you can use this code on each page according to your needs but your dispatch will change server-side state only!!!, which means you can access them on the client-side.
export const getServerSideProps = wrapper.getServerSideProps(async ({ store, query }) => {
try {
const { id } = query
const res = await api.get('/abc', { params: { id } })
await store.dispatch(action)
return {
props: {
id,
data: res.data,
isServer: typeof window === 'undefined',
}
}
} catch (error) {
return {
props: {
errorCode: 409,
message: "Data Unavailable"
}
}
}
})
In the end, I ditched both options because it provides a bad user experience.
My recommendation is to use getInitProps and check if the page is rendering on the server then call API and save props in client-side, otherwise call API in the client a and save it.

How to use onSnapshot to update props through Redux

I'm learning how to code and I'm really struggling with the following issue:
I'm building a chat app and I need to display new messages as soon as they are submitted. As a result, I thought about using onSnapshot(). Every time I used onSnapshot() in basic one-page exercises, it worked. Now, however, I have a project with 3 folders (src; public; functions). For all my functionality, I got/sent data using this.props.functionName() and manage state with Redux and then, the backend would return a promise.
My question is, how do I use onSnapshot to update my props given that I cannot call the function nor use return.
I tried using the admin sdk directly in the components, but firebase issued a warning in the console saying I should only use it in the backend.
Basically, how do I send the following array to the component I need it to be sent to without invoking the function?
exports.messages = (req, res) => {
db.collection('messages').onSnapshot(snapshot => {
let messages = [];
snapshot.forEach(doc => {
messages.push(doc.data())
});
})
}
Thanks in advance!
You can find in this tutorial a way to update firebase props that might work for you. The sample code they use is:
useEffect(() => {
const unsubscribe = props.firebase
.db.collection('myCollectionName')
.onSnapshot(snapshot => {
if (snapshot.size) {
// we have something
** Handle returned data **
} else {
// it's empty
}
})
return () => {
unsubscribe()
}
}, [props.firebase])
And this other one for handling returned data:
let myDataArray = []
snapshot.forEach(doc =>
myDataArray.push({ ...doc.data() })
)
setData(myDataArray)

Callback not called in database .on method

I'm using react-native-firebase package, react-native and redux.
When I'm trying to initialize data by fetching tasks from firebase database. I'm calling async redux action from my react component's componentDidMount() method.
componentDidMount() {
let uid = null;
if (this.props.sessionState.authUser) {
uid = this.props.sessionState.authUser.uid;
}
this.props.fetchToDos(uid);
}
And everything works fine on the first build of React Native app, but when I save and reload, for some reason the callback of my db call is not called and it keeps not being called until I completely rebuild my app. Again it worked fine on the first load of an app.
Here is the call to database:
export const fetchToDos = (uid) => async dispatch => {
var userId = firebase.auth().currentUser.uid;
database.ref().child('users/' + userId + '/tasks/').on('value', snapshot => {
console.log('INSIDE');
dispatch({
type: 'FETCH_TASKS',
payload: snapshot.val()
});
})
};
I'm porting my app from the web and this code works perfectly fine with my web app.
This Github issue seems like your problem, I think you should give it a look. Good luck!

How to update the UI after a delete mutation in react-apollo

I want the UI of my app to update after running a delete mutation in a react apollo component. The delete operation was successful but the UI did not update after the delete mutation. Below is a copy of my code, is there anything I am not getting right?
const deleteRoom = async (roomId, client = apolloClient) => {
const user = await getUserDetails();
const deleteResponse = await client.mutate({
mutation: DELETE_ROOM,
name: 'deleteRoom',
variables: {
roomId,
},
update: (cache, { data: roomDelete }) => {
const data = cache.readQuery({
query: GET_ROOMS_QUERY,
variables: {
location: user.location,
office: '',
page: 1,
perPage: 8,
},
});
data.allRooms.rooms = data.allRooms.rooms.filter(
room => room.id !== roomDelete.deleteRoom.room.id,
);
console.log(data, '======');
cache.writeQuery({
query: GET_ROOMS_QUERY,
data,
});
},
});
return deleteResponse;
};
I expected that the UI will be updated after executing the delete mutation, however, the UI doesn't get updated unless I do a force refresh.
N:B
When I console log the data, it actually removed the deleted data after filtering it out of the array. The updated data is what I am writing back to the cache
This behaviour is described in docs:
The difference between cache.writeQuery and client.writeQuery is that the client version also performs a broadcast after writing to the cache. This broadcast ensures your data is refreshed in the view layer after the client.writeQuery operation. If you only use cache.writeQuery, the changes may not be immediately reflected in the view layer. This behavior is sometimes useful in scenarios where you want to perform multiple cache writes without immediately updating the view layer.
You can use refetchQueries option in mutate to force refresh.
Make sure the object going into update as the "data" includes returning values and is not an empty object and thus will not update UI.
update: (cache, { data: roomDelete }) // log data
So the mutations can work but no UI changes at once without update passing data forward.
And cache.writeQuery works fine.

Nuxt.js Loading data serverside with nuxtServerInit and Vuex

Currently i am working on storing data for a job opening application.
For the backend i use Laravel and for the frontend i use Nuxt.js
I am new to Nuxt, so i'm kinda stuck on the following issue.
I have a page for creating a new job opening called new-job.vue. I also created a store called jobs.js for handling the states.
On new-job.vue i have a form with data that has to be rendered in a list before the form starts.Like a list of all countries etc.. in order for me to select them in the form.
At this point i'm using asyncData within the export default on new-job.vue:
<script>
export default {
asyncData(context) {
return context.app.$axios
.$get('jobs/create')
.then(data => {
//context.store.dispatch('jobs/getTypes', data.types)
context.store.dispatch('jobs/getPlatforms', data.platforms)
context.store.dispatch('jobs/getCountries', data.countries)data.branches)
// return {
// loadedPost: { ...data, id: context.params.postId }
// }composer required barr
})
.catch(e => context.error(e))
},
computed: {
types () { return this.$store.state.jobs.types },
platforms () { return this.$store.state.jobs.platforms },
countries () { return this.$store.state.jobs.countries },
},
}
The asyncData method works and the lists of types, platforms and countries are getting filled with data from the database and the state from the Vuex store gets updated. .Only the data is being rendered on the client side.
I prefer this data to be loaded server side, so i was looking at nuxtServerInit. Only can someone explain to me how i can make this happen.
I placed an async call inside the export default of new-job.vue:
async nuxtServerInit ({ commit, state }, { app }) {
let res = await axios.get(`jobs/create`)
console.log(res)
commit('setPlatforms', res.data.platforms)
commit('setTypes', res.data.types)
commit('setCountries', res.data.countries)
},
I created the commits in the mutations of the jobs.store, but the states are not being updated.
What am i doing wrong and/or what am i missing?
Or maybe another question, is nuxtServerInit the way to go? Or is loading these lists of data on the clientside not a big deal?
UPDATE:
I use modules mode for the store, so i created a store called jobs.js. Inside this file i tried to call nuxtServerInit as well, but i didn't get any response.
nuxtServerInit(vuexContext, context) {
return context.app.$axios
.$get('jobs/create')
.then(data => {
console.log(data)
})
.catch(e => context.error(e))
},
From nuxtServerInit API reference in Nuxt.js documentation:
If the action nuxtServerInit is defined in the store, Nuxt.js will call it with the context (only from the server-side).
In other words, it is a reserved store action available only in store/index.js file and if defined will be called on server-side before rendering requested routes.
Only asyncData and fetch methods are available within pages.

Categories