CANNOT CREATE NEW RECORD USING LWC - SALESFORCE - salesforce

I am new in LWC and would like to know that why my code is not working. My requirement is to call this LWC from VF page. Using the LWC I have to create a new record in my Object PRODUCT2__C.
I have attached the javascript and html files of my LWC. Please let me know what I am doing wrong as I am getting error :
"Error creating record
An error occurred while trying to update the record. Please try again."
//tUButton.html
<!--
#File Name : tUButton.html
#Description :
#Author : ChangeMeIn#UserSettingsUnder.SFDoc
#Group :
#Last Modified By : ChangeMeIn#UserSettingsUnder.SFDoc
#Last Modified On : 12/10/2019, 12:49:09 PM
#Modification Log :
Ver Date Author Modification
1.0 12/9/2019 ChangeMeIn#UserSettingsUnder.SFDoc Initial Version
-->
<template>
<lightning-card title="Add Number of Layers And Palletes" icon-name="standard:record">
<div class="slds-m-around_medium">
<lightning-input label="Id" disabled value={Product2}></lightning-input>
<lightning-input label="TU per Layer" onchange={handleChangeLayer} class="slds-m-bottom_x-small"></lightning-input>
<lightning-input label="Layer per Pallete" onchange={handleChangePallete} class="slds-m-bottom_x-small"></lightning-input>
<lightning-button label="Submit" variant="brand" onclick={submitProduct}></lightning-button>
</div>
</lightning-card>
</template>
// tUButton.js
//
import { LightningElement, track, api } from 'lwc';
import { createRecord } from 'lightning/uiRecordApi';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import Product2_OBJECT from '#salesforce/schema/Product2';
import NAME_FIELD from '#salesforce/schema/Product2.Name';
//import SKULayers_FIELD from '#salesforce/schema/Product2.SKU_External_Id__c'
export default class LdsCreateRecord extends LightningElement {
// #track productId;
#track name = '';
#api recordId;
handleChangeLayer(event) {
this.productId = undefined;
this.name = event.target.value;
}
handleChangePallete(event) {
this.productId = undefined;
this.name = event.target.value;
}
submitProduct() {
const fields = {};
fields[NAME_FIELD.fieldApiName] = this.name;
const recordInput = { apiName: Product2_OBJECT.objectApiName, fields };
createRecord(recordInput)
.then(product => {
this.productId = product.id;
this.dispatchEvent(
new ShowToastEvent({
title: 'Success',
message: 'Product created',
variant: 'success',
}),
);
})
.catch(error => {
this.dispatchEvent(
new ShowToastEvent({
title: 'Error creating record',
message: error.body.message,
variant: 'error',
}),
);
});
}
}
Thanks in Advance if anyone can help in identifying the issue.

Related

Unable to connect to Room: Invalid Access Token issuer/subject - Twilio visio room issues

I'm using twilio, Symfony 5 with the help of this tuto :
https://www.twilio.com/blog/create-group-video-chat-app-symfony-php-twilio-react
to create a video chat.
Upon entering the name of the room and launching the visio, I got the following error in the browser's console :
Unable to connect to Room: Invalid Access Token issuer/subject
I understand it's caused because the token generated by the route access_token must not be right.
I've created a normal twilio account then generated the API key, kept account sid, api key sid and api secret on my .env file.
Just in case I recreated a new api key to see if it changed something but didn't.
I've checked the doc for my error (https://www.twilio.com/docs/api/errors/20103) , but the solutions did not solve my problem.
Chat.js file:
import React, { useState } from "react";
import axios from "axios";
import Video from "twilio-video";
const Chat = () => {
const [roomName, setRoomName] = useState('');
const [hasJoinedRoom, setHasJoinedRoom] = useState(false);
const joinChat = event => {
event.preventDefault();
if (roomName) {
axios.post('/access_token', { roomName }, ).then((response) => {
console.log('RESPONSE: ');
console.log(response.data.token);
connectToRoom(response.data.token);
setHasJoinedRoom(true);
setRoomName('');
}).catch((error) => {
console.log(error);
})
} else {
alert("You need to enter a room name")
}
};
const connectToRoom = (token) => {
const { connect, createLocalVideoTrack } = Video;
let connectOption = { name: roomName };
connect(token, connectOption).then(room => {
console.log(`Successfully joined a Room: ${room}`);
const videoChatWindow = document.getElementById('video-chat-window');
createLocalVideoTrack().then(track => {
videoChatWindow.appendChild(track.attach());
});
room.on('participantConnected', participant => {
console.log(`Participant "${participant.identity}" connected`);
participant.tracks.forEach(publication => {
if (publication.isSubscribed) {
const track = publication.track;
videoChatWindow.appendChild(track.attach());
}
});
participant.on('trackSubscribed', track => {
videoChatWindow.appendChild(track.attach());
});
});
}, error => {
console.error(`Unable to connect to Room: ${error.message}`);
});
};
return(
<div className="container">
<div className={"col-md-12"}>
<h1 className="text-title">Symfony React Video Chat</h1>
</div>
<div className="col-md-6">
<div className={"mb-5 mt-5"}>
{!hasJoinedRoom && (
<form className="form-inline" onSubmit={joinChat}>
<input type="text" name={'roomName'} className={"form-control"} id="roomName"
placeholder="Enter a room name" value={roomName} onChange={event => setRoomName(event.target.value)}/>
<button type="submit" className="btn btn-primary">Join Room</button>
</form>
)}
</div>
<div id="video-chat-window"/>
</div>
</div>
)
};
export default Chat;
TokenController file to generate user's token :
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Twilio\Jwt\AccessToken;
use Twilio\Jwt\Grants\VideoGrant;
class TokenController extends AbstractController
{
/**
* #Route("/token", name="token")
*/
public function index()
{
return $this->render('token/index.html.twig', [
'controller_name' => 'TokenController',
]);
}
/**
* #param Request $req
* #return \Symfony\Component\HttpFoundation\JsonResponse
* #Route("access_token", name="access_token", methods={"POST"})
*/
public function generateToken(Request $req) {
$accountSid = getenv('ACCOUNT_SID');
$apiKeySid = getenv('API_SID');
$apiKeySecretSid = getenv('API_SECRET');
$identity = uniqid();
$roomName = json_decode($req->getContent());
$token = new AccessToken(
$accountSid,
$apiKeySid,
$apiKeySecretSid,
3600,
$identity
);
$grant = new VideoGrant();
$grant->setRoom($roomName->roomName);
$token->addGrant($grant);
return $this->json(['token' => $token->toJWT()], 200);
}
}
And this line in the **app.js** :
ReactDOM.render(<Chat/>, document.getElementById("root"));
With the proper imports.
UPDATE
Solution found! Thanks for the help !
getenv() method was the issue.
I now inject my .env info in my controller as parameters as follow :
services.yaml
parameters:
app.env.ACCOUNT_SID: '%env(resolve:ACCOUNT_SID)%'
app.env.API_KEY: '%env(resolve:API_KEY)%'
app.env.API_SECRET: '%env(resolve:API_SECRET)%'
And recover them in the controller
Controller to recover the data
public function somename() {
$sid = $this->getParameter('app.env.ACCOUNT_SID');
$apiKey = $this->getParameter('app.env.API_KEY');
$apiSecret = $this->getParameter('app.env.API_SECRET');
$identity = uniqid();
$token = new AccessToken(
$sid,
$apiKey,
$apiSecret,
3600,
$identity
);
}
And works like a charm
may be it could help those who has this issue.
I have found that the default region used in the exemple code was "US1" and that I have create my API KEY in the region "IE1".
Creating and using an API KEY made in the US1 region has resolve my problem and has made the exemple code work.
Now because I am in Europe region, i will try to figure how to set the default region as "IE1" in the SDK.

Observable to Array *ngFor saying undefined

I am new to Angular. I have a Node and Express backend pulling data from an MS SQL database. If I go to the endpoint URL it displays my data as JSON. I am running on localhost so I set a proxy for CORS. I have a class that defines the data, a service that pulls the data from the endpoint and a component that tries to set an array equal to the data pulled from the service. The HTML has an *ngFor that is supposed to loop through the values and display them in a grid.
If I call my data in my component through my service, so this.userService.getUsers(), and do a console.log I can see the recordset in the browser console. I try to set the array equal to the userService.getUsers() and then call the array and I get "undefined". Being that I am new, I have tried to follow the Heroes tutorial and that did not work. I spent a day searching Google and trying different solutions that I have come across but they all come up as undefined. I will attach the code here. If someone can guide me a bit, it would be much appreciated.
User class defining User:
export class User{
id: number;
ccn: string;
firstName: string;
lastName: string;
email: string;
}
User Service doing Http request:
import { Injectable } from '#angular/core';
import { User } from './user';
import { USERS } from './mock-users';
import { MessageService } from './message.service';
import { Observable, of } from 'rxjs';
import { HttpClient, HttpHeaders } from '#angular/common/http';
import { catchError, map, tap } from 'rxjs/operators';
#Injectable({
providedIn: 'root'
})
export class UserService {
private userURL = 'api/users'
//private userURL = 'localhost:5000'
httpOptions = {
headers: new HttpHeaders({ 'Content-Type': 'application/json' })
};
constructor(
private http: HttpClient,
private messageService: MessageService) { }
//getUsers(): Observable<User[]> {
// this.messageService.add('UserService: fetched users');
// return of(USERS);
//}
/** GET users from the server */
getUsers(): Observable<User[]> {
//console.log('getting users');
return this.http.get<User[]>("http://localhost:5000/api/user")
.pipe(
tap(_ => this.log('Fetched users')),
catchError(this.handleError<User[]>('getUsers', []))
);
//return this.http.get<User[]>("http://localhost:5000/api/user");
//console.log('got users');
}
/* GET heroes whose name contains search term */
searchUsers(term: string): Observable<User[]> {
if (!term.trim()) {
// if not search term, return empty hero array.
return of([]);
}
return this.http.get<User[]>(`${this.userURL}/?ccn=${term}`).pipe(
tap(_ => this.log(`found users matching "${term}"`)),
catchError(this.handleError<User[]>('searchUsers', []))
);
}
addUser (user: User): Observable<User> {
return this.http.post<User>(this.userURL, user, this.httpOptions).pipe(
tap((newUser: User) => this.log(`added user w/ id=${newUser.id}`)),
catchError(this.handleError<User>('addUser'))
);
}
private handleError<T> (operation = 'operation', result?: T) {
return (error: any): Observable<T> => {
console.error(error);
this.log(`${operation} failed: ${error.message}`);
return of(result as T);
};
}
private log(message: string) {
this.messageService.add(`User service: ${message}`);
}
}
Display Users Component TS file:
import { Component, OnInit } from '#angular/core';
//import { USERS } from '../mock-users';
import { UserService } from '../user.service';
import { User } from '../user';
import { Observable, of } from 'rxjs';
import { catchError, map, tap } from 'rxjs/operators';
import { element } from 'protractor';
#Component({
selector: 'app-display-users',
templateUrl: './display-users.component.html',
styleUrls: ['./display-users.component.css']
})
export class DisplayUsersComponent implements OnInit {
users: User[] = [];
constructor(private userService: UserService) { }
//users$ = this.getUsers();
ngOnInit() {
this.getUsers();
console.log(this.userService.getUsers());
this.userService.getUsers().forEach(element => {
console.log(element);
});
}
getUsers(): void {
/*this.userService.getUsers()
.subscribe(users => this.users = users);*/
const userObservable = this.userService.getUsers();
userObservable.subscribe((userData: User[]) => {
this.users = userData;
});
}
}
Display Users Component HTML:
<div class="clr-row">
<div class="clr-col-lg-11 clr-col-md-11 clr-col-11 main-div">
<div class="card card-style" style="box-shadow: 0 0 0 0;">
<div class="card-header">
<h1><img src="../assets/images/BSOLOGO_gray.png" class="title-img"><span class="title"> Users</span></h1>
</div>
<div class="card-block">
<div class="card-title">
<clr-datagrid>
<clr-dg-column>CCN</clr-dg-column>
<clr-dg-column>Last Name</clr-dg-column>
<clr-dg-column>First Name</clr-dg-column>
<clr-dg-column>Email</clr-dg-column>
<clr-dg-row *ngFor="let user of users">
<clr-dg-cell>{{user.ccn}}</clr-dg-cell>
<clr-dg-cell>{{user.lastName}}</clr-dg-cell>
<clr-dg-cell>{{user.firstName}}</clr-dg-cell>
<clr-dg-cell>{{user.email}}</clr-dg-cell>
</clr-dg-row>
<clr-dg-footer>{{users.length}} users</clr-dg-footer>
</clr-datagrid>
</div>
</div>
</div>
</div>
</div>
Any help would be greatly appreciated!
UPDATED
Ypu can replace getUsers on both classes by these. HTML looks fine to me. I converted users to public too.
//userService
getUsers(callback: Function) {
return this.http.get<User[]>("http://localhost:5000/api/user")
.subscribe(
response => callback(response)
);
}
//Component
public users: User[] = [];
getUsers(): void {
this.userService.getUsers((result) => {this.users = result;})
}
If you do not need it to be Observable you can use toPromise() and using async/await makes it waaay easier
Service
async getUsers(): Promise<User[]> {
return await this.http.get<User[]>('http://localhost:5000/api/user').toPromise();
}
Component.ts
users: User[] = [];
async ngOnInit() {
this.users = await this.userService.getUsers();
}
Component.html
<clr-datagrid *ngIf="users">
<clr-dg-column>CCN</clr-dg-column>
<clr-dg-column>Last Name</clr-dg-column>
<clr-dg-column>First Name</clr-dg-column>
<clr-dg-column>Email</clr-dg-column>
<clr-dg-row *ngFor="let user of users">
<clr-dg-cell>{{user.ccn}}</clr-dg-cell>
<clr-dg-cell>{{user.lastName}}</clr-dg-cell>
<clr-dg-cell>{{user.firstName}}</clr-dg-cell>
<clr-dg-cell>{{user.email}}</clr-dg-cell>
</clr-dg-row>
<clr-dg-footer>{{users.length}} users</clr-dg-footer>
</clr-datagrid>
My issue has been resolved. In my SQL statement I was calling SELECT * FROM table FOR JSON PATH which was creating a weird object being pulled from the server. Removing the FOR JSON PATH provided JSON data. Then the second part of my issue was mapping my DB fields with my user class.
This was done like this:
request.query('SELECT * FROM Table ORDER BY myField', function (err, recordset) {
if (err) console.log(err);
const records = recordset.recordset;
const result = records.map(r => { return { id: r.tableID, field1: r.dbField1, field2: r.dbField2, field3: r.dbField3, field4: r.dbField4}});
res.send(result);
});
I hope this helps someone! Thanks to everyone that posted to help me.

TypeError: date[("get" + method)] is not a function in React-big-calendar

I am trying to change the view from month to week but in meantime it give me an error . I am new to react and react-big-calendar could someone please help me how to solve this problem . When I change calendar view to month it working fine but when I changed it to week or day so it give me an error. please help me Thanks
Code
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import MyCalendar from 'react-big-calendar';
import CustomToolbar from './toolbar';
import Popup from 'react-popup';
import Input from './input';
import moment from 'moment';
import { fetchEvents, createEvent, updateEvent, deleteEvent } from '../actions';
// Setup the localizer by providing the moment (or globalize) Object to the correct localizer.
const localizer = MyCalendar.momentLocalizer(moment); // or globalizeLocalizer
class Calendar extends Component {
componentDidMount() {
this.props.fetchEvents();
}
//RENDER SINGLE EVENT POPUP CONTENT
renderEventContent(slotInfo) {
const date = moment(slotInfo.start).format('MMMM D, YYYY');
return (
<div>
<p>Date: <strong>{date}</strong></p>
<p>Subject: {slotInfo.taskChage}</p>
<p>Time : {slotInfo.time}</p>
<p>Date : { slotInfo.date}</p>
<p>Notes : {slotInfo.notes}</p>
<p>User Id : {slotInfo.userId}</p>
</div>
);
}
//ON SELECT EVENT HANDLER FUNCTION
onSelectEventHandler = (slotInfo) => {
Popup.create({
title: slotInfo.title,
content: this.renderEventContent(slotInfo),
buttons: {
right: [{
text: 'Edit',
className: 'info',
action: function () {
Popup.close(); //CLOSE PREVIOUS POPUP
this.openPopupForm(slotInfo); //OPEN NEW EDIT POPUP
}.bind(this)
}, {
text: 'Delete',
className: 'danger',
action: function () {
//CALL EVENT DELETE ACTION
this.props.deleteEvent(slotInfo.id);
Popup.close();
}.bind(this)
}]
}
});
}
//HANDLE FUNCITON ON SELECT EVENT SLOT
onSelectEventSlotHandler = (slotInfo) => {
this.openPopupForm(slotInfo); //OPEN POPUP FOR CREATE/EDIT EVENT
}
//POPUP-FORM FUNCTION FOR CREATE AND EDIT EVENT
openPopupForm = (slotInfo) => {
let newEvent = false;
let popupTitle = "Update Event";
if(!slotInfo.hasOwnProperty('id')) {
slotInfo.id = moment().format('x'); //Generate id with Unix Millisecond Timestamp
slotInfo.title = null;
slotInfo.taskChange = null;
slotInfo.message=null;
popupTitle = "Create Event";
newEvent = true;
}
let titleChange = function (value) {
slotInfo.title = value;
};
let taskChange = function (value) {
slotInfo.taskChage = value;
};
let timeChange = function (value) {
slotInfo.time = value;
};
let dateChnage = function ( value){
slotInfo.date=value;
};
let notesChange = function ( value){
slotInfo.notes=value;
};
let userId = function ( value){
slotInfo.userId=value;
};
Popup.create({
title: popupTitle,
content: <div>
<Input onChange={titleChange} placeholder="Subject" />
<Input onChange={taskChange} placeholder="Task Type" />
<Input onChange={timeChange} placeholder="Time"/>
<Input onChange={dateChnage} placeholder="Date"/>
<Input onChange={notesChange} placeholder="Notes"/>
<Input onChange={userId} placeholder="User Id"/>
</div>,
buttons: {
left: ['cancel'],
right: [{
text: 'Save',
className: 'success',
action: function () {
//CHECK THE ID PROPERTY FOR CREATE/UPDATE
if(newEvent) {
this.props.createEvent(slotInfo); //EVENT CREATE ACTION
} else {
this.props.updateEvent(slotInfo); //EVENT UPDATE ACTION
}
Popup.close();
}.bind(this)
}]
}
});
}
//EVENT STYLE GETTER FOR SLYLING AN EVENT ITEM
eventStyleGetter(event, start, end, isSelected) {
let current_time = moment().format('YYYY MM DD');
let event_time = moment(event.start).format('YYYY MM DD');
let background = (current_time>event_time) ? '#DE6987' : '#8CBD4C';
return {
style: {
backgroundColor: background
}
};
}
render() {
return (
<div className="calendar-container">
<MyCalendar
popup
selectable
localizer={localizer}
defaultView={MyCalendar.Views.WEEK}
components={{toolbar: CustomToolbar}}
views={['week']}
style={{height: 600}}
events={this.props.events}
eventPropGetter={(this.eventStyleGetter)}
onSelectEvent={(slotInfo) => this.onSelectEventHandler(slotInfo)}
onSelectSlot={(slotInfo) => this.onSelectEventSlotHandler(slotInfo)}
/>
{console.log(this.props.event)}
<Popup />
</div>
);
}
}
function mapStateToProps(state) {
return {
events: state.events
};
}
function mapDispatchToProps(dispatch) {
return bindActionCreators({
fetchEvents,
createEvent,
updateEvent,
deleteEvent
}, dispatch);
}
export default connect(mapStateToProps, mapDispatchToProps)(Calendar);
For anyone finding this, a few things.
Your localizer handles manipulation of dates under the hood. All dates that you pass in (from your getNow and date props, all the way to your individual event.start and event.end dates) should be true JS Date objects.
Your various method props, for working with events or setting styling or whatever, will receive true JS Date objects, not localizer objects or UTC strings or whatever.
RBC will only work with true JS Date objects. If you pass it moment instances or date strings or something else, it might display but it will operate funky, as RBC will handle all conversions under the hood, and it's use of the date-arithmatic library, internally, works with true JS Dates and not your localizer objects.
const formatted = moment(time).toDate();
I had the same issue before. The solution depends on your date field.
If date field is like start: new Date('2024-09-02T08:00:00-04:00'),
then use this: startAccessor="start"
If date field is like "start": "2024-01-15T08:00:00-04:00",
then use this: startAccessor={(event) => { return new Date(event.start) }}
In the 2nd case, below will throw same error.
startAccessor={(event) => { return moment(event.start) }}
Hope this helps.
Make sure that you have the correct values for start and end keys in your event object,
your event object should be like :
data = [
{
title: "My event",
allDay: false,
start: new Date(2020, 10, 25, 10, 0), // 10.00 AM
end: new Date(2020, 10, 25, 11, 0), // 2.00 PM
}
]
this happens when the date you are trying to display is "String" when actually "date" is an "Object" type, then you could do something like this:
as event data example convert string to date object.
{
id: 8,
title: "Meeting",
start: new Date("2022-05-12T08:00:00.000Z"),
end: new Date("2022-05-12T09:00:00.000Z")
}

how to delete multiple items with checkbox in ionic 3

I would like to know how to delete multiple items from the list in Ionic 3, using CheckBox, here is my code, in the delete () function I do not know how to only exclude the products that are checked with the checkbox. I thought that this would work but did not delete anything . If anyone can help me, thank you.
produto.html
<ion-item-sliding *ngFor="let produto of produtos">
<ion-item>
<input [(ngModel)]="modelo[produto.id]" value="{{produto.id}}" name="modelo" type="checkbox" ng-checked="produto.checked">{{produto.id}}
<h1> {{ produto.barra }}</h1>
<h3> {{ produto.deposito_nome }}</h3>
<h3> {{ produto.quantidade }}</h3>
<!--<h2 class="price">{{ produto.preco | currency:'BRL':true }}</h2> -->
</ion-item>
</ion-item-sliding>
</ion-list>
<button ion-button (click)="excluir()">Excluir Todos</button>
import { Component } from '#angular/core';
import { DatabaseProvider } from '../../providers/database/database';
import { SQLiteObject } from '#ionic-native/sqlite';
import { NavController, NavParams, ToastController } from 'ionic-angular';
import { InventarioProvider, Product } from '../../providers/inventario/inventario';
import { RestProvider } from '../../providers/rest/rest';
import { HomePage } from '../home/home';
#Component({
selector: 'page-inventario',
templateUrl: 'inventario.html',
})
export class InventarioPage {
produtos: any[] = [];
modelo: any[] = [];
this.model = new Product();
if (this.navParams.data.id) {
this.inventarioProvider.get(this.navParams.data.id)
.then((result: any) => {
this.model = result;
})
}
}
ionViewDidEnter() {
this.getAllProdutos();
}
getAllProdutos() {
this.inventarioProvider.getAll()
.then((result: any[]) => {
this.produtos = result;
});
}
excluir() {
this.produtos.forEach(function (produto) {
if (produto.checked) {
this.modelo[produto.id] = produto.checked;
return this.dbProvider.getDB()
.then((db: SQLiteObject) => {
let sql = 'delete from inventario where id = ?';
let data = [produto.id];
return db.executeSql(sql, data)
})
}
})
}
}
Hey I never worked with SQlite but assuming the other parts of your code work including the db handling, you need to do something like the below in your delete method:
excluir() {
// create comma separated list of products to be deleted from db:
const toBeDeleted = this.produtos.filter(produto => produto.checked === true);
// now execute db script to delete multiple products:
return this.dbProvider.getDB().then((db: SQLiteObject) => {
// here i might be wrong but you should be able to delete all items with ids in one operation, don't use loop as it may get expensive:
db.delete("inventario", "id IN (?)", toBeDeleted.join())
db.close()
}).then(() => {
// now do the modelo step (not sure what is this though in your case):
toBeDeleted.forEach(produto => {
this.modelo[produto.id] = produto.checked;
})
// finally update product array by filtering out deleted items:
this.produtos = this.produtos.filter(produto => produto.checked === false);
})
}
Please note I am not entirely sure how you use delete multiple items using SQlite, but I hope you know that part. I think you might need to do this way:
db.delete("inventario", "id IN (" + toBeDeleted.join() + ")", null)

Must contain a query definition

Iam new to react-native and appsync,graphql.we are trying to implement an appsync app using react-native when i tried to run its is throwing an error saying
14:16:38: Must contain a query definition.
* null:null in getQueryDefinition
- node_modules/apollo-cache-inmemory/lib/bundle.umd.js:649:64 in diffQueryAgainstStore
- node_modules/apollo-cache-inmemory/lib/bundle.umd.js:559:32 in readQueryFromStore
- node_modules/apollo-cache-inmemory/lib/bundle.umd.js:899:38 in read
- node_modules/apollo-cache-inmemory/lib/bundle.umd.js:992:23 in readQuery
* null:null in update
- node_modules/apollo-client/bundle.umd.js:1609:0 in
- node_modules/apollo-utilities/lib/bundle.umd.js:818:21 in tryFunctionOrLogError
* null:null in
- node_modules/apollo-cache-inmemory/lib/bundle.umd.js:961:22 in performTransaction
- node_modules/apollo-client/bundle.umd.js:1473:0 in markMutationResult
- node_modules/apollo-client/bundle.umd.js:797:20 in next
- node_modules/zen-observable-ts/node_modules/zen-observable/lib/Observable.js:150:3 in notifySubscription
- node_modules/zen-observable-ts/node_modules/zen-observable/lib/Observable.js:195:5 in onNotify
* null:null in next
- node_modules/zen-observable-ts/node_modules/zen-observable/lib/Observable.js:150:3 in notifySubscription
* null:null in flushSubscription
- node_modules/zen-observable-ts/node_modules/zen-observable/lib/Observable.js:190:26 in
* null:null in
- node_modules/promise/setimmediate/core.js:37:14 in tryCallOne
- node_modules/promise/setimmediate/core.js:123:25 in
- ... 10 more stack frames from framework internals
I tried to trace out the error in apollo-cache but i couldnt find one.Am getting this when ever i press send button.
import React, { Component } from 'react';
import { KeyboardAvoidingView, Text, Button, TextInput, StyleSheet, Alert } from 'react-native';
export default class ChatInput extends Component {
constructor(props) {
super(props);
this.userid = props.userid;
this.state = {
text: ''
}
}
handleSend = () => {
if (this.state.text === '') {
return false;
}
const chat = {
userid: this.userid,
text: this.state.text,
createdAt: new Date().toISOString()
}
this.props.onSubmit(chat);
this.setState({
text: ''
})
this.textInput.clear();
}
render() {
return (
<KeyboardAvoidingView>
<TextInput ref={input => { this.textInput = input }} placeholder="Message.."
onChangeText={(text) => this.setState({text})} onSubmitEditing={this.handleSend}
autoFocus={true} blurOnSubmit={false} returnKeyType="send"></TextInput>
<Button title="Send" onPress={this.handleSend}></Button>
</KeyboardAvoidingView>
);
}
}
const ChatInputData = compose(
graphql(PostMessage, {
options: {
fetchPolicy: 'no-cache'
},props: (props) => ({
onSubmit: chat => {
props.mutate({
variables: chat,
optimisticResponse: {
__typename: 'Mutation',
post: {
__typename: ChatHistory,
id: chat.createdAt,
userid: chat.userid,
text: chat.text,
createdAt: chat.createdAt
}
},
update: (proxy, {data: {post}}) => {
const data = proxy.readQuery({ query: PostMessage });
data.listPostMessages.items.push(Object.assign({}, post));
proxy.writeData({query: listPostMessages, data});
}
})
}
})
})
)(ChatInput)
Please help me out!.Thanks in advance
At this line :
const data = proxy.readQuery({ query: PostMessage });
I do not see a reference to PostMessage where you want to define your query.
The error means that in the imported PostMessage, the query could not be found. Make sure it looks like this: (and not the shorthand equivalent)
query postMessage($id: ID!) {
postMessage(id: $id) {
id
title
}
}
I resolved this error by correcting my mutation ie PostMesssage in my case.This error
Must contain a query definition
mainly occur if your query is incorrect which you have written in graphql. Start seeing how you passing your variables and how you use them and how you define them.
I also got this error when I had added new resolver functions (in new files) but failed to include references to these resolvers into graphql's executable schema.

Resources