I am doing a query and have already logged the result. Everything works as it should, however when I want to continue working with the result it always is "undefined" (see 2nd logging).
I am sure I am missing out on something obvious here but would really love to get your help :)
render() {
let saved;
this.props.apolloClient
.watchQuery<Query>({
query: gql`
query($id: ID!) {
element(id: $id) {
children {
... on TextNote {
name
description
type
}
}
}
}
`,
variables: { id: 0 }
})
.subscribe(({ data: { element: { children } } }) => {
console.log(children); // this is the wanted result
saved = children;
});
console.log("save");
console.log(saved); // this is undefined for some reason
If children gives you the correct result, can you not just assign your variable saved to your this.props.apolloClient function and return children inside the subscribe call?
Something like:
render() {
const saved = this.props.apolloClient
.watchQuery<Query>({
query: gql`
query($id: ID!) {
element(id: $id) {
children {
... on TextNote {
name
description
type
}
}
}
}
`,
variables: { id: 0 }
})
.subscribe(({ data: { element: { children } } }) => {
console.log(children); // this is the wanted result
return children; // <-- return the value here
});
console.log("save");
console.log(saved); // <-- should have children assigned to saved
Related
I have an object defined like this. I want to access the role object and push a value into it. I couldn't do it with a map anyway. Any help?
Example: That exactly what i want. I want to map and find role and push some items. I filter the object if there is the same element i just change its value
interface IInitial {
init: string;
lang: string;
}
interface IInitialValues {
role: IInitial[];
addPrivs: string;
}
const [initialValues, setInitialValues] = useState<IInitialValues[]>([]);
initialValues.map((item) => item.role)
.push({
init: "test",
lang: "TR",
})
OR
initialValues
.map((item: any) => item === name)
.filter((item: any) => {
if (item.lang === activeLang) {
item.init = value;
}
});
You use state so you have to return new collection, and not modify the initial collection
///Update the state
setInitialValues(prevValues =>{
return prevValues.map(item => {
///rule to find the item to add roles to
if (item.addPrivs === 'somethig') {
///return cloned object with one more role item
return {...item, roles:[...item.role, { init: 'newInit', lang: 'new lang' } ] }
} else {
/// does not match the rule return unmodified item
return item;
}
} )
} )
initialValues.map((item) => item.role)
.push(...initialValues, {
init: "test",
lang: "TR",
})
I am trying to provide functionality in my webpage for editing state data.
Here is the state structure
state = {
eventList:[
{
name: "Coachella"
list: [
{
id: 1,
name: "Eminem"
type: "rap"
}
{
id: 2,
name: "Kendrick Lamar"
type: "rap"
}
]
}
]
}
I want to be able to edit the list arrays specifically the id, name, and type properties but my function doesn't seem to edit them? I currently pass data I want to override id name and type with in variable eventData and an id value specifying which row is selected in the table which outputs the state data.
Here is the function code:
editPickEvent = (eventData, id) => {
const eventListNew = this.state.eventList;
eventListNew.map((event) => {
event.list.map((single) => {
if (single.id == id) {
single = eventData;
}
});
});
this.setState({
eventList: eventListNew,
});
};
When I run the code the function doesn't alter the single map variable and I can't seem to pinpoint the reason why. Any help would be great
edit:
Implementing Captain Mhmdrz_A's solution
editPickEvent = (eventData, id) => {
const eventListNew = this.state.eventList.map((event) => {
event.list.map((single) => {
if (single.id == id) {
single = eventData;
}
});
});
this.setState({
eventList: eventListNew,
});
};
I get a new error saying Cannot read property list of undefined in another file that uses the map function to render the state data to the table?
This is the part of the other file causing the error:
render() {
const EventsList = this.props.eventList.map((event) => {
return event.list.map((single) => {
return (
map() return a new array every time, but you are not assigning it to anything;
editPickEvent = (eventData, id) => {
const eventListNew = this.state.eventList.map((event) => {
event.list.forEach((single) => {
if (single.id == id) {
single = eventData;
}
});
return event
});
this.setState({
eventList: eventListNew,
});
};
const editPickEvent = (eventData, id) => {
const updatedEventList = this.state.eventList.map(event => {
const updatedList = event.list.map(single => {
if (single.id === id) {
return eventData;
}
return single;
});
return {...event, list: updatedList};
});
this.setState({
eventList: updatedEventList,
});
}
Example Link: https://codesandbox.io/s/crazy-lake-2q6ez
Note: You may need to add more checks in between for handling cases when values could be null or undefined.
Also, it would be good if you can add something similar to the original data source or an example link.
Turns out primitive values are pass by value in javascript, which I didn't know and why the assignment wasn't working in some of the previous suggested answers. Here is the code that got it working for me:
editEvent = (EventData, id) => {
const eventListNew = this.state.eventList.map((event) => {
const newList = event.list.map((single) => {
return single.id == id ? EventData : single;
});
return { ...event, list: newList };
});
this.setState({
eventList: eventListNew,
});
};
I want to create a new variable line and make it contain nested data.
What I am expecting as result:
{
description: "descriptionString",
vatInfo : {
vatAccount: {
vatCode : "vatCode"
}
}
}
How I am doing it:
export function changeProductOnLine(originalLine, product, customer, invoice) {
let line = { ...originalLine, product }
if (product) {
const vatCode = getProductVatCode(line, invoice)
line.description = buildLineDescription(product.name, product.description)
line.vatInfo.vatAccount.vatCode = "v10"
return line
}
Is it correct what I am doing ? Can it work ?
What you're doing is close, but you need to keep in mind that when you use a spreader like that, what you'll end up with is this:
{
description: "descriptionString",
vatInfo : {
vatAccount: {
vatCode : "vatCode"
}
},
product: {
description: "descriptionString",
vatInfo : {
vatAccount: {
vatCode : "vatCode"
}
}
}
}
What I think you want is for product to overwrite the values, but not end up with a 'product' property in your object, based on what you explained you wanted. Try this:
export function changeProductOnLine(originalLine, product, customer, invoice) {
if (product) {
return {
...originalLine,
// since these are the last thing in the new obj it will overwrite anything in the obj
description: buildLineDescription(product.name, product.description),
vatInfo: {
vatAccount : {
vatCode: getProductVatCode(line, invoice)
}
}
}
} else {
return line
}
}
This way, you also don't end up creating a new variable in memory just to modify it slightly then return it. It all happens at once, and ONLY if you have a arg 'product' value other than undefined or null
Here is the initial state of my reducer, and I need to set it up in this way due to some post processing I need to do:
const initialState = {
showAll: {
photos: null
}
}
Basically, I have a page where you see all your photos, and you can tag certain ones as your pinned photos.
Here's part of my reducer logic:
if (state.showAll.photos) {
const showAllState = state.showAll.photos;
showAllState.map(m => {
if (action.payload.id === m.id) {
m.pinned = true;
}
});
showAllAfterPin = showAllState;
} else {
showAllAfterPin = state.showAll.photos;
}
However, I get an error saying cannot read property 'photos' of undefined and I'm not sure what I am doing wrong.
Might be easier to just set your photos in initialState to empty array [] instead of null.
Another thing, your reducer should not mutate your state object.
Doing const showAllState = state.showAll.photos doesn't make it a new object.
Last thing, showAllState.map(...) needs to return an item inside the function body. It will create a new array.
Here's something you can do...
const { photos = [] } = state.showAll;
const updatedPhotos = photos.map(photo => {
if (action.payload.id === photo.id) {
return Object.assign({}, photo, { pinned: true })
}
return photo;
});
// return entire state if this is inside your root reducer
return {
...state,
showAll {
...state.showAll,
photos: updatedPhotos
}
}
Its a mongoose/express app, I have a route like this:
// ..
Posts.find({})
.then(function(posts) {
var data = _.chain(posts).filter(function(post) {
if(post.comment) {
return post.updatedAt <= post.comment.lastCreatedAt;
} else {
return true;
}
}).each(function(post) {
if(post.comment) {
post.status = 'OK';
} else {
post.status = 'NOT OK';
}
console.log("post")
console.log(post)
console.log("post.status")
console.log(post.status)
}).value();
})
// ..
But the log is
"post"
{
_id: ***,
title: 'test',
content: 'test',
user: ***
}
"post.status"
OK
why there's no status in first console.log(post) ?
The post is a Document object which means it has a custom toJSON method that only yields the properties of your schema and the _id.
You can get an object representation of the document via the toObject method.