apollo client offsetLimitPagination not working - javascript

I have a hook..
export function useLazyProposalList() {
const [getQueueData, { loading, data, error, fetchMore }] = useLazyQuery(PROPOSAL_LIST, {
fetchPolicy: 'no-cache',
});
const proposalList = React.useMemo(() => {
if (!data) {
return null;
}
return transformProposals(data);
}, [data]);
return {
getQueueData,
fetchMore,
loading,
data: proposalList,
error,
};
}
In the component
const {
getQueueData,
data: queueData,
fetchMore: fetchMoreProposals,
// loadMore: loadMore,
} = useLazyProposalList();
If user clicks on fetch more button, I call: fetchMoreProposals .
await fetchMoreProposals({
variables: {
offset: visibleProposalList.length,
},
});
but this doesn't update my data. I read that we should use offsetLimitPagination, but my data from query is not array itself. It's like this: queue { id: '1', items:[] } and because of this, offsetLimitPagination doesn't work. So I tried merge
cache: new InMemoryCache({
typePolicies: {
Query: {
fields: {
queue: {
keyArgs: false,
merge(existing, incoming) {
console.log(existing, incoming);
if (!incoming) return existing;
if (!existing) return incoming;
},
},
},
},
}
but in the console, it just prints refs instead of real data.
What could be the issue ?

Related

Pinia|Vue3 I can't access the property of the object that returned from the Pinia action

first of all I am using the Mockjs to simulate the backend data:
{
url: "/mockApi/system",
method: "get",
timeout: 500,
statusCode: 200,
response: { //
status: 200,
message: 'ok',
data: {
'onlineStatus|3': [{
'statusId': '#integer(1,3)',
'onlineStatusText': '#ctitle(3)',
'onlineStatusIcon': Random.image('20*20'),
'createTime': '#datetime'
}],
'websiteInfo': [{
'id|+1': 1,
}]
}
}
}
the data structure would be: https://imgur.com/a/7FqvVTK
and I retrieve this mock data in Pinia store:
import axios from "axios"
import { defineStore } from "pinia"
export const useSystem = defineStore('System', {
state: () => {
return {
systemConfig: {
onlineStatus: [],
},
}
},
actions: {
getSystemConfig() {
const axiosInstance = axios.interceptors.request.use(function (config) {
// Do something before request is sent
config.baseURL = '/mockApi'
return config
}, function (error) {
// Do something with request error
return Promise.reject(error);
})
axios.get('/system/').then(res => {
this.systemConfig.onlineStatus = res.data.data.onlineStatus
})
// console.log(res.data.data.onlineStatus)
axios.interceptors.request.eject(axiosInstance)
}
}
})
I use this store in the parent component Profile.vue:
export default {
setup() {
const systemConfigStore = useSystem()
systemConfigStore.getSystemConfig()
const { systemConfig } = storeToRefs(systemConfigStore)
return {
systemConfig,
}
},
computed: {
getUserOnlineStatusIndex() {
return this.userData.onlineStatus//this would be 1-3 int.
},
getUserOnlineStatus() {
return this.systemConfig.onlineStatus
},
showUserOnlineStatusText() {
return this.getUserOnlineStatus[this.getUserOnlineStatusIndex - 1]
},
},
components: {UserOnlineStatus }
}
template in Profile.vue I import the child component userOnlineStatus.vue
<UserOnlineStatus :userCurrentOnlineStatus="userData.onlineStatus">
{{ showUserOnlineStatusText }}
</UserOnlineStatus>
here is what I have got https://imgur.com/fq33uL8
but I only want to get the onlineStatusText property of the returned object, so I change the computed code in the parent component Profile.vue:
export default {
setup() {
const systemConfigStore = useSystem()
systemConfigStore.getSystemConfig()
const { systemConfig } = storeToRefs(systemConfigStore)
return {
systemConfig,
}
},
computed: {
getUserOnlineStatusIndex() {
return this.userData.onlineStatus//this would be 1-3 int.
},
getUserOnlineStatus() {
return this.systemConfig.onlineStatus
},
showUserOnlineStatusText() {
return this.getUserOnlineStatus[this.getUserOnlineStatusIndex - 1]['onlineStatusText']//👀I chage it here!
},
},
components: {UserOnlineStatus }
}
but I will get the error in the console and it doesn't work:
https://imgur.com/Gb68Slk
what should I do if I just want to display the specific propery of the retrived data?
I am out of my wits...
I have tried move the store function to the child components, but get the same result.
and I google this issue for two days, nothing found.
Maybe it's because of I was trying to read the value that the Profile.vue hasn't retrieved yet?
in this case, how could I make sure that I have got all the value ready before the page rendered in vue3? Or can I watch this specific property changed, then go on rendering the page?
every UX that has data is coming from remote source (async data) should has spinner or skeleton.
you can use the optional chaining for safe access (if no time to await):
return this.getUserOnlineStatus?.[this.getUserOnlineStatusIndex - 1]?.['onlineStatusText']

Trying to refetch the data using Apollo query

I am trying to refetch the data after an action is done but i am failing at refetching and the page is not refreshing with the data.
Below is the code for mutation and fetch queries:
const {
data: designHubProjectData,
loading: designHubProjectDataLoading,
error: designHubProjectDataError
} = useQuery(ALL_DESIGNHUB_PROJECTS, {
fetchPolicy: 'network-only',
variables: {
order: [{ projectNumber: 'DESC' }]
}
});
const [insertEmployeeDesignHubProjectBookmarkMutation] = useMutation(
INSERT_EMPLOYEE_DESIGNHUB_PROJECT_BOOKMARK,
{
refetchQueries: [ // here i am calling two queries after insert
{
query: EMPLOYEE_DESIGNHUB_PROJECT_BOOKMARK,
variables: {
order: [{ projectNumber: 'DESC' }]
}
},
{
query: ALL_DESIGNHUB_PROJECTS,
fetchPolicy: 'network-only',
variables: {
order: [{ projectNumber: 'DESC' }]
}
}
]
}
);
and then below is the method where i am calling above mutation
const handleAddBookmark = record => {
insertEmployeeDesignHubProjectBookmarkMutation({
variables: {
employeeId: loggedInEmployee.id,
projectNumber: record.projectNumber
}
}).then(({ data }) => {
if (data.insertEmployeeDesignHubProjectBookmark.ok) {
notification.success({
message: 'Success',
description: 'Successfully bookmarked the project.'
});
} else {
const errors = data.insertEmployeeDesignHubProjectBookmark.errors.join(', ');
notification.error({
message: 'Error',
description: `Adding bookmark to the project failed: ${errors}.`
});
}
});
};
i am not sure where I am doing wrong with the above code. Could any one please let me know any suggestion or ideas how to refetch make it work, many thanks in advance
I have solved this problem by assigning refetch to Oncompleted method like as below,
const {
data: designHubProjectBookmarkData,
loading: designHubProjectBookmarkDataLoading,
error: designHubProjectBookmarkDataError,
refetch: refetchBookmarkProjects
} = useQuery(EMPLOYEE_DESIGNHUB_PROJECT_BOOKMARK, {
fetchPolicy: 'network-only',
variables: {
order: { projectNumber: 'DESC' }
}
});
const [insertEmployeeDesignHubProjectBookmarkMutation] = useMutation(
INSERT_EMPLOYEE_DESIGNHUB_PROJECT_BOOKMARK,
{
onCompleted: refetchBookmarkProjects
}
);
if it incase anyone in the future looking for the same, this is an example.

My function is not loading in the right way

When I load my page my datacollection is null or undefined, but I want my data from the api to be filled in as soon as the site loads.
<script>
import LineChart from './LineChart.js'
import axios from 'axios'
export default {
name: 'Graph',
components: {
LineChart
},
data () {
return {
ratingOne: null,
ratingTwo: null,
ratingThree: null,
datacollection: null
}
},
created: function () {
console.log(this.datacollection)
this.fillData()
},
mounted () {
},
methods: {
getZeroes () {
axios.get('MYAPI').then(response => {
this.ratingOne = response.data.Rates.filter(rates =>
rates.rate === 0).length
return this.ratingOne
})
},
fillData () {
this.getOnes()
console.log(this.getZeroes())
this.getOnes()
this.getTwos()
this.datacollection = {
labels: ['DÃ¥rlig oplevelse', 'Okay oplevelse', 'Rigtig god
oplevelse'],
datasets: [
{
backgroundColor: ['#FF0000', '#D3D3D3', '#00CC00'],
data: [this.ratingOne, this.ratingTwo, this.ratingThree]
}
]
}
}
}
}
</script>
When i use a click function it works and it loads my graph with the data I want, but it does not work when my page I loaded. Can anyone tell me why?
When i console log "this.getZeroes())" it just tells me "undefined"
and when i click my button with update
<button #click="fillData()">Randomize</button>
it works
getZeroes, getOnes, getTwos are asynchronous functions. After getZeroes function and such are run, the data is not ready. That's why dataCollection doesn't have the right data.
You need to you promise to wait for the response finish, and update the data to the chart.
getZeroes will return a promise.
getZeroes () {
return axios.get('MYAPI').then(response => {
this.ratingOne = response.data.Rates.filter(rates => rates.rate === 0).length
return this.ratingOne
})
},
in the fillData. We must wait them to finish by using then
fillData () {
this.getOnes()
.then(() => this.getZeroes())
.then(() => this.getTwos())
.then(() => {
this.datacollection = {
labels: ['DÃ¥rlig oplevelse', 'Okay oplevelse', 'Rigtig god oplevelse'],
datasets: [
{
backgroundColor: ['#FF0000', '#D3D3D3', '#00CC00'],
data: [this.ratingOne, this.ratingTwo, this.ratingThree]
}
]
}
})
}
Or we can even run the gets parallel and get data at once by using Promise.all
Promise.all([this.getOnes(), this.getTwos(), this,getThrees()])
.then(() => { /* the rest here */ })

Trying to use this.props.dispatch and returns that is not a function

I am trying to delete an item from DB but when I access the function is saying _this.props.dispatch is not a function. (In '_this.props.dispatch((0, _actions.deleteJob)(_this.props.id))', '_this.props.dispatch' is undefined)
Here is my code where I am calling the function to delete my item. The function onDelete() I am calling it after user interaction.
class JobItem extends Component {
constructor(props) {
super(props)
this.state = {
activeRowKey: null,
deleting: false
};
}
onDelete = () => {
this.setState({deleting: true});
this.props.dispatch(deleteJob(this.props.id)); // HERE is the error
}
render() {
const swipeSettings = {
autoClose: true,
onClose: (secId, rowId, direction) => {
this.setState({ activeRowKey: null });
},
onOpen: (secId, rowId, direction) => {
this.setState({ activeRowKey: this.props.id });
},
right: [
{
onPress: () => {
const deletingRow = this.state.activeRowKey;
Alert.alert(
'Alert',
'Are you sure you want to delete?',
[
{text: 'No', onPress: () => console.log('Cancel Pressed'), style:'cancel'},
{text: 'Yes', onPress: () => {
this.onDelete();
// Refresh Job List
this.props.parentFlatList.refreshJobList(deletingRow);
}},
],
{ cancelable: true }
)
},
text: 'Delete', type: 'delete'
}
],
rowId: this.props._id,
sectionId: 1
}
And here is the deleteJob() function where it actually delete it from DB
export function deleteJob(job_id) {
return function (dispatch) {
return axios.delete(JOB_URL(user_id, job_id), {
headers: { authorization: token }
}).then((response) => {
dispatch(removeJob(job_id));
}).catch((err) => {
dispatch(addAlert("Couldn't delete job."));
});
};
}
JobItem
var renderJobs = () => {
return this.props.jobs.map((job) => {
return (
<JobItem
parentFlatList={this}
key={job._id}
title={job.title}
shortDescription={job.shortDescription}
logo={job.avatar}
company={job.company}
id={job._id}/>
)
})
}
var mapStateToProps = (state) => {
return {
jobs: state.jobs
}
}
module.exports = connect(mapStateToProps)(JobList);
Any idea how shall I solve this?
I think you forgot to pass dispatch to JobItem
<JobItem
parentFlatList={this}
key={job._id}
title={job.title}
shortDescription={job.shortDescription}
logo={job.avatar}
company={job.company}
id={job._id}
dispatch={this.props.dispatch} /* <-- this one here */
/>
One way to fix the problem is to put JobItem inside container.
Something like this
module.exports = connect(mapStateToProps,dispatch=>({dispatch}))(JobItem);

How to re render table component upon receiving a notification from web socket in React JS?

Im using React table and loading a page which displays a table with data fetched from an API. Im also listening on a web socket and right now, whenever something is sent over a web socket, Im printing a console message. Now I want to reload the table(in turn making the API call) when I receive any update on the web socket.
class TableExp extends React.Component {
constructor() {
super();
this.state = {
tableData: [
{
resourceID: '',
resourceType: '',
tenantName: '',
dealerID: '',
status: '',
logFilePath: '',
supportPerson: '',
lastUpdatedTime: '',
},
],
//testMessage: [{ message: 'Initial Message' }],
};
}
componentDidMount() {
this.websocket = new WebSocket(socket);
this.websocket.onopen = () => {
axios.get('https://myapi.com', {
headers: {},
responseType: 'json',
})
.then((response) => {
this.setState({ tableData: response.data });
});
console.log('Socket Opened');
};
this.websocket.onmessage = (event) => {
const data = (JSON.parse(event.data));
const status = data.status;
console.log(data.status);
this.forceUpdate();
if (status === 'failed') {
console.log('Error message received');
this.reloadTable();
}
};
this.websocket.onclose = () => {
this.statusDispatcher('closed');
};
}
reloadTable() {
this.forceUpdate();
}
render() {
const { tableData } = this.state;
return (
<ReactTable
data={tableData}
noDataText="Loading.."
columns={[
{
columns: [
{
Header: 'Dealer ID',
accessor: 'dealerId',
id: "dealerId",
},
{
Header: 'Location',
id: "dealerId",
},
{
columns: [
{
filterable: false,
Header: 'File Path',
accessor: 'logFilePath',
},
{
filterable: false,
Header: 'Date',
accessor: 'Date',
},
],
},
]}
defaultPageSize={20}
style={{
height: '450px', // This will force the table body to overflow and scroll, since there is not enough room
}}
className="-striped -highlight"
/>
);
}
You can simple setState within onmessage
this.websocket.onmessage = (event) => {
let data = [];
const status = data.status;
if (status === 'failed') {
console.log('Error message received');
// And do nothing, or empty table
} else {
data = JSON.parse(event.data);
}
this.setState({ tableData: data });
};

Categories

Resources