How to set react state values from another state values? - javascript

I have an array of objects in state:
const [formFields, setFormFields] = useState([
{
height: 45,
label: "tv",
placeholder: "555",
name: "tv",
maxWidth: 203,
value: dataValues.tv,
priority: 1
},
{
height: 45,
label: "radio",
placeholder: "50%",
name: "radio",
maxWidth: 126,
value: dataValues.radio,
priority: 2
},
{
height: 45,
label: "instagram",
placeholder: "60%",
name: "instagram",
maxWidth: 126,
value: dataValues.instagram,
priority: 3
}
]);
I need each state value to be updated when another state updates (when I click on submit money button each state value should update), but it is not updating.
you can check the demo
any help please?

Your input elements have their value set based upon your formFields object. When you initially make the object, you use values from your dataValues object, and dataValues will automatically update based on your apiData object due to what you wrote in your useEffect hook, however you never actually wrote anything to update formFields itself.
The following code should make it work as is,
const newFormFields = [...formFields];
newFormFields[0].value = apiData.tv;
newFormFields[1].value = apiData.radio;
newFormFields[2].value = apiData.instagram;
setFormFields(newFormFields);
However I'd strongly advise refactoring. It seems like you've got a whole lot of needless redundancy here.
You mentioned in a comment that can't use indexes. In that case, something like this should work.
const newFormFields = [...formFields];
newFormFields.map(field => (field.value = apiData[field.name]));
setFormFields(newFormFields);

Related

Fetch live-updating data from an IDB (Dexie) using Vue.js

I am trying to display a live logs table using Vue(quasar)+Dexie.
I managed to display the data using the basic example from the dexie doc page:
export default {
name: "Logs",
setup() {
const columns = [
{
name: "ts",
label: "TimeStamp",
field: "ts",
align: "left",
format: (val, row) => date.formatDate(val, "HH:mm:ss:SSS"),
},
{
name: "action",
label: "Action",
field: "action",
align: "left",
format: (val, row) => val,
},
{
name: "status",
label: "Status",
field: "status",
align: "left",
format: (val, row) => val,
},
{
name: "data",
label: "Data",
field: "data",
align: "left",
format: (val, row) => {
return val;
},
},
];
const pagination = ref({
sortBy: "ts",
descending: true,
page: 1,
rowsPerPage: 10,
});
return {
columns,
pagination,
dialog: [],
logs: useObservable(
liveQuery(() => useDatabase.logs.reverse().limit(10).toArray())
),
};
},
};
I get a new Log entry every 1 second.
I am almost sure that the whole bulk of data is re-fetched and not appended. Am I right?
Is there a better practice for loading live updating data from a table than this? (if it's really as i described)
Instead of re-loading all the data from IDB, to just fetch the newly added entries and append them.
I have the same exact situation when displaying a live updating chart (using ApexCharts).
but in this case, I fetch 256 samples per second. I want the components to render the data "automatically" using Vues superpowers while pointing to a ref.
Usually when working with frontend frameworks, and specifically Vue, I create some kind of a variable let logs = ref({...}) and whenever there new data, it gets rendered only when and where it's needed. It doesn't re-render the whole bulk all over again.
I hope my problem is clear, and if not, the examples or my way of thought is understood. I might be thinking this wrong, but i'd be happy to learn from others experience.

Changing Vue Data Object

UPDATED CODE
<template>
<swiper-slide v-for="(photon,key) in $store.state.photons" :key='key'>
<radial-gauge :value='photon.tempF'
:options="photon.GaugeOptions.optionsLastTempF"></radial-gauge>
</swiper-slide>
</template>
store.js
export const store = new Vuex.Store({
state: {
photons: {},
token: '',
},
mutations: {
setUser(state, value) {
value.data.forEach(element => {
state.photons[element.id].user = element.data
state.photons[element.id].GaugeOptions.optionsLastTempF.highlights[0].to=parseInt(element.data.tempAlert,10)
state.photons[element.id].GaugeOptions.optionsLastTempF.highlights[1].from=parseInt(element.data.tempAlert,10)+1
});
}},
actions: {
async getData(context) {
let db = []
let photon = {}
db = await axios.get('http://13.14.13.1:3300/DB')
db.data.forEach(item => {
if ([Object.keys(item)[0]] in photon) {
let dataString = (Object.values(item)[0]).split(',')
photon[Object.keys(item)[0]].GaugeOptions={}
photon[Object.keys(item)[0]].GaugeOptions.optionsLastTempF={
title: 'Last Temp',
units: "°F",
minorTicks: 10,
majorTicks: ['0', '20', '40', '60', '80', '100', '120', '140', '160'],
maxValue: 160,
highlights: [{
"from": 0,
"to": 0,
"color": "rgba(0,255,0)"
},
{
"from":0,
"to": 160,
"color": "rgba(255,0,0)"
},
],
colorPlate: '#222',
colorUnits: '#ccc',
colorTitle: '#eee',
colorNumbers: '#eee',
width: 200,
height: 200
}
context.commit('setData', photon)
}
}
}
This code currently works if I go from the homepage to my chart page where this gauges are, but if i refresh the page the gauges have the right values but they aren't being properly update.
UPDATE
so after adding a v-if to my component it now loads properly with everything. I'm now having trouble with how I would call an update function on the gauge?If i'm doing the mutation in my vuex store how would i reference my component to call an update?
So, typically, Vuejs does not watch nested objects. I'd recommend that you rework you code a bit to avoid this. This should help: Vue.js - How to properly watch for nested data
Additionally, it looks like you are trying to reference the Vuex Store object, but you are using the data method rather than the computed method, so you won't get updates on that.

javascript push() method for adding object to array of objects

var model = {
cats: [
{
clickCount: 0,
name: "Panther",
imgUrl: "images/cat1.png"
},
{
clickCount: 0,
name: "Tiger",
imgUrl: "images/cat2.png"
},
{
clickCount: 0,
name: "Rocky",
imgUrl: "images/cat3.png"
},
{
clickCount: 0,
name: "Marshal",
imgUrl: "images/cat4.png"
},
{
clickCount: 0,
name: "Simpson",
imgUrl: "images/cat5.png"
},
{
clickCount: 0,
name: "Kajol",
imgUrl: "images/cat6.png"
}
]
};
catObject = {
name: document.getElementById('text-name').value,
url: document.getElementById('text-url').value,
count: document.getElementById('text-count').value
};
model is an array of objects. I am trying to add another object using model.cats.push(catObject);
where text-name, text-url, text-count are ids of textboxes in a form.
I am not getting desired results. I am seeing that only catObject.name is getting pushed onto model.cats and catObject.url and catObject.count is not getting added and hence 'undefined' are values of the model.cats.imgUrl and model.cats.clickCount.
I can add full code if required. I tried so may things.. Could someone check if I am missing anything here? Thanks in advance.
Correction
model is not an array of objects rather model is an object that contains a property (i.e. cats) which is an array of objects.
You're correct
From your description, it is clear that you have successfully pushed catObject into cats using model.cats.push(catObject);
What went wrong
You might have used loop to access the elements inside cats array and got undefined for model.cats.clickCount and model.cats.imgUrl of only the last object you've pushed because you named properties of catObject as url and count (i.e. instead of imgUrl and clickCount). So, just change the property names to imgUrl and clickCount to fix the issue.
Corrected code here

Values inserted into combobox are undefined

So I've created a combobox as such and when I attempt to insert using the addOption function it appears to work on some level. It shows a place in the combobox where it should be but it's a blank space. When I click on it, it shows undefined. Any idea what I'm doing wrong?
var infoCellList = [
{type: "settings", position: "label-left", labelWidth: 90, inputWidth: 130},
{type: "combo", name: "truckSelect", label: "Truck", value: ""}
];
var myFormInformation = vehicles_layout.cells('a').attachForm(infoCellList);
var truckSelectCombo = myFormInformation.getCombo("truckSelect");
truckSelectCombo.addOption("This is a test");

AngularJS: is $$hashkey a reliable key

Question
I'm interested in the properties of $$hashkey on angular arrays/objects.
Would each generated hashkey be the same each time you reload a
page; a quick test tells me yes but I somewhat assumed it
wouldn't?
If you updated/added to the existing array, would the old hashkey's
stay consistent?
If the above is true, is there a way to fetch from an array using
the hashkey? - of cause I could roll my own but before I recreate the wheel I thought I'd ask.
Example:
Views would include:
form data (example has 1 form)
element data (example has 2 elements)
element options data (example has 2 options per element)
Fetch method:
angular.get($$hashkey);
You would then pass the hashkey of the element and it would return a reference to that array inside the full array.
Lastly the data would be:
{
form_id: 1
form_desc: 'xxx',
form_name: 'name 1',
Elements: [
{
element_id: 1,
element_name: 'element1',
default_value: null,
disabled: "0",
element_type: "image",
ElementOptions: [
{
show: false,
sort_order: 0,
value: "ar",
},
{
show: true,
sort_order: 1,
value: "rw",
}
],
},
{
element_id: 2,
element_name: 'element2',
default_value: null,
disabled: "0",
element_type: "image",
ElementOptions: [
{
show: false,
sort_order: 0,
value: "ar",
},
{
show: true,
sort_order: 1,
value: "rw",
}
],
}
]
}
$$hashkeys will only be computed for functions and objects so if you wish to track anything that isn't one of those types then you have that limitation.
$$Hashkeys look like ...
(function||object): N
...
Where N is just an incremental value being adjusted + 1 for each $$HashKey computed.
So, in many cases this could be the same value across page loads. But loading data that is asynch, will cause differences when multiple data sources are being queried as part of page initialization and order of return cannot be guranteed. In cases like that you would have to marshall all your asynch data and then assign that data to your scope in a specific order to ensure consistent $$hashkeys.
Moving items around in an array that is linked to our DOM (via ng-repeat) will not change that items $$hashkey. Deleting it and re-adding it will.
I would not use $$Hashkey for my own housekeeping as it is intended to be internal to AngularJS.
I've used this internal private property when I had no identifiers.
I think, it's pretty usable, but not recommended.

Categories