VueJs Method is changing directly a response - javascript

I have a parent component and ı am making a query to backend in there, then with the help of the navbar and my activeView data in the parent component with on Clicks I render a new child page and pass a prop from my response with the help of v-if in vue. But one of the functions of the method is changing my prop in the parent component also IT CHANGES MY RESPONSE how can this be possible.
This is the before mount of my child component:
beforeMount() {
console.log(this.plansPropOrg);
this.plansProp = this.plansPropOrg;
this.tempPlan = this.plansProp.currentPlan;
console.log(this.plansProp);
this.propsToData();
}
the problematic function is propsToData when ı comment out here it is normal but ı have to call it.
And here is the my parent when ı make the query:
await axios.post("xxxxx/yyyyyyy").then(res => {
console.log("heyyo");
console.log(res);
this.plansData = res.data.data;
console.log(this.plansData);
});
And here is the props to data, it is just translating boolean values to english. But in the response, (when this if is true) ı see the values as translations.
propsToData() {
//TODO: Burdaki if' ifsubscriber olarak değişecel
console.log("AAA");
console.log(this.plansProp);
if (this.plansProp.isSubscriber) {
console.log("BBBBB");
this.plansProp.currentPlan.analytics
? (this.plansProp.currentPlan.analytics = this.$t(
"settings.plans.active"
))
: (this.plansProp.currentPlan.analytics = this.$t(
"settings.plans.inactive"
));
}
}
How can this be possible how can it change the response?

You're copying the response and the plansProp object by reference, meaning both objects are pointing to the same place in memory. When you change one of them, the other still points to the same place in memory, meaning when you retrieve it it's going to be the same object.
You want to do either a shallow (Object.assign()) or a deep (JSON.parse(JSON.stringify())) copy, depending on how your object is structured.
More info on that here https://www.javascripttutorial.net/object/3-ways-to-copy-objects-in-javascript/.

Related

How to print Clarifai API returned response?

help... I'm making a project that detects food ingredients using Clarifai API Food model. When the API scans the image, it returns the response via console.log. How do you get THAT output from the API (console.log) and print it in the webpage. sorry, newbie aspiring web dev here.Image of website,console.log, and JS code
Instead of console logging the response, you should define a key value pair in the state of the component:
// the initial value of each key in state should match what data you are storing
this.state = {
input: '',
foodUrl: '',
prediction: {},
};
After the file has received the API response, instead of console logging the response you would write:
this.setState({ prediction: response.outputs[0].data.concepts[0] });
Next you would pass it in to the component you are using to display the response within the render portion of App.js:
<ComponentToRenderAPIResponse prediction={this.state.prediction} />
Within that child component, you would then write something like this within the render portion:
render() {
return (
<div>`Detected Food: ${prediction.name}`</div>
<div>`Prediction Value: ${prediction.value}`</div>
)
}
Instead of storing the entire object displayed in your console, you could just access the name and value key value pairs and store them as separate fields within your state object. Then pass both the name and value as different props to the child component. Also you might want to consider different html tags than the divs I used above as well as adding CSS styling to both tags.

How to handle vue composition api with lazy and route components?

In my vue application I have a component page that contains five components. I also use vue composition api.
each component is lazy, it resolve when the component is in the viewport. because of that I need to write the logic only inside the component. (not in the parent).
so far so good, but two of components inside product.vue depend of the route params value. say /product/2.
the product.vue looks like that:
<intro> -> just a raw text (no need to fetch from the server, not need to wait to load)
<foo> -> need data from the server base on the productId from the route.params.
<txt> -> just a raw text not need to get the data from the server
<bar> -> need data from the server base on the productId from the route.params.
Important notes:
In case I don't need data from the server like intro I want to render it immediately. so for all similar components in this page.
for example intro render right way, the foo will render when it enter to the viewport and display a loader and when the data is resolved it change to the data.
I want to see the page ASAP. so each component have its own loader.
Here I become with some problems:
One: I need to know if the product exist. if not it need to be redirect to 404 page. so where to put this logic? each component or the parent component? I think the parent component, but when it take 2 min to load the data I'll get a blank screen seince the components are not ready and not be render. which is conflict with "Important notes".
Two: when the productId is change (navigate to another product) the foo and bar need to resolve the data, so in those two components I need to listen to the route change (which makes duplication in my code) (and slow performance?) and still I need to check if the productId is exist or not.
in this example the items don't change because it need to trigger the useProduct function.
setup() {
const { route, router } = useRouter();
const productIdToLoad = computed(() => route.value.params.productId);
const { items } = useProduct({ productId: productIdToLoad });
return { items }
}
and if I do it in watch I lose the reference
setup() {
const { route, router } = useRouter();
const items = ref([]);
const productIdToLoad = computed(() => route.value.params.productId);
watch(productIdToLoad, (v) => {
items = useProduct({ productId: v });
});
return { items }
}

Vue/Vuex - How to retrieve data from grandchildren

started with VueJs for the first time
yesterday and now I'm stuck..
I have a parent component who has child items that also has a child inside them (I call them grandchildren). I want to fetch data from all the grandchildren when i click a button in the parent but i can't figure out how.
In my mind a want to call an event from parent to to all the grandchildrens that they should store their data to vuex store. Is this possible somehow or is there another way to do this?
// Data
blocks = [
{
id: 1,
type: 'HeadingBlock',
title: 'Hello',
color: 'blue'
},
{
id: 2,
type: 'ImageBlock',
image_id: 2
}
];
// App.js
<ContentBlocks :blocks="blocks" / >
// ContentBlock.vue
<ContentBlockItem v-for="(block, index) in blocks" :component="block.type" ... />
// ContentBlockItem.vue
<component :is="component" :block="block" /> // Grandchild
// component aka the grandchild (eg. HeadingBlock.vue)
data() {
return {
title: 'Hello - I want save the changed data for this heading',
color: 'blue'
}
}
So, the only call to action happens in the parent by a "save"-button. And i want as little logic in grandchildren as possible (to make it easy to create new ones, like a "ParagraphBlock").
Thx in advance
It is possible to emit() a global Event that all your components subscribe to - however it seems rather impractical. (e.g. this.$root.emit('saveData') in parent; in all children to listen to it: this.$root.on('saveData'))
A more practical approach is to store all your component data in the store in the first place. And have each component retrieve its state from the store. (e.g. in a computed property: title() { return this.$store.myComponent.title }.
The trick here is obviously to set all your store-data correctly (e.g. with componentIDs to match it correctly). To do this you need to be aware, that vuex does not support maps or sets. Also, you have to set each property/element individually - you cannot set nested structures in one go bu thave to do it recursively. Hereby Arrays have to be filled with native array methods (push(), splice()) and Object properties have to be set with Vue.set(object, key, value).
For accessing data between parent and child component you can use one of the best features of vue is vuex store. It's really helpful when you want to pass data to child component and update that data in child and again pass back to parent without the use of props and event emit.
Here is a link you can follow for your web application
https://medium.com/dailyjs/mastering-vuex-zero-to-hero-e0ca1f421d45
https://medium.com/vue-mastery/vuex-explained-visually-f17c8c76d6c4
I hope this will help you.

Where to act on changed child properties in React JS

I'm confused, and I have searched a lot for the answer to this (seemingly) basic question.
I'm learning React, and I have a rather common component hierarchy with one top component (lets call it App) which contains a number of subcomponents (a grid, a graph, a table etc).
They all show information regarding one product.
Now when I select a row in the grid, I want to inform the other subcomponents about the change. App therefore passes a callback method
onSelectedProduct={this.onSelectedProduct}
to the grid. This gets called OK. In this App method I set the state:
onSelectedProduct(product) {
this.setState({ product: product });
}
In its render(), App has declared another subcomponent:
<ProductGraph product={this.state.product} />
Since ProductGraph needs to fetch some data asynchronously "to-be-rendered" later, where should I catch this property change??
The old "componentWillReceiveProps" sounded like the proper place, but will be deprecated and should not be used, I understand.
I have also tried shouldComponentUpdate, getDerivedStateFromProps and even to catch it in render, but they all have downsides and eventually lead to horrible code.
Somewhere, somehow, I should be able to detect that props.product !== state.product and issue an async load call for the data...
When the async method I call returns with the data, it will set the state and render itself.
So where is the optimal place to catch changed properties?
I have read a lot about the React Lifecycle but I just can't seem to find this basic information. Am I stupid or maybe blind? Or have I got this completely wrong somehow?
You are looking for componentDidUpdate() the lifecycle method that triggers when a component receives new props or has an updated state.
https://reactjs.org/docs/react-component.html#componentdidupdate
In your ProductGraph component, you would do something like:
componentDidUpdate(prevProps){
if(this.props.product !== prevProps.product){
fetch(`myApi/${this.props.product}`)
.then(res => res.json())
.then(data => this.setState({ data: data })) <-- identify what you need from object
.catch((errors) => {
console.log(errors)
})
}
}

Multi level props in react

I've recently started learning react. I can't understand this:
this.props.message.text
I know that message is an object with a key value pair in it, the key being text.
But my problem is when we want to pass the prop to the component:
<Component message={message}>
My question is why should we write message={message}?
Why shouldn't we write message={message.text} instead so that we know we want text?
How does it know we want text in the message object?
It depends on what the Component is doing. Let's say you have more properties in your message object, e.g :
{
text: 'this is my message',
author: 'odiwxe',
sentAt: '2018-05-30T12:30:00'
}
Then your Component might want all that information in order to display it so you could pass it as you have done like:
<Component message={message}>
Otherwise, if your Component only cares about the message text you could potentially change it to something like this:
<Component messageText={message.text}>
It's up to you!
Actually, it does not.
When we want the text of the message we have to access the data using the props passed to the child component in this way:
{this.props.message.text}
So, when any child component requires data which is sent by it's parent you need to tell the object name in which you require the data in child.
for Example:
<Parent Component {
//Some code//
<ChildComponent propsName = {propsData}
}
Then this data will be accessible in child component in this form:
<ChildComponent
{this.props.propsName}
}
So, this is the way of passing the data from parent to child and for achieving this you need to use props.
//Update
It has used task for the task but task.id for the key because they just want the key in that case and task object is used in the component for some other functioning like printing the text written in that which cannot be fetched from task.id individually.
According to me, the task object is somewhat like this:
task{
"text": "value"
}

Categories

Resources