accessing an array gives weird "refimpl" - vue.js

I can't do data._rawValue or data._value to only get the arrays.
It doesn't recognize these keywords.
How should I approach this problem?
Thank you in advance.

there is a sample.
const data = ref([{ name: 1 }, { name: 2 }]);
const testClick = function () {
for (const item in data.value) {
console.log(data.value[item]);
console.log("hello");
}
console.log(data);
};
onMounted(() => {
testClick();
});
I think you may wrap the data with the ref function from vue.
Therefore,everytime you want to read the value from data,you had to read from the (data.value).
I suggest you to check the offical document of vue.
https://vuejs.org/api/reactivity-core.html#ref
Besides,if the type of data is object or array,its better to wrap it with reactive function.And then you can just read it directly.
I used to feel puzzle about this situation,too.
Im not good at writing in english.

Related

Access or modify petite-vue data outside app

I'm using petite-vue as I need to do very basic UI updates in a webpage and have been drawn to its filesize and simplicity. I'd like to control the UI's state of visible / invisible DOM elements and class names and styles of various elements.
I have multiple JavaScript files in my app, I'd like to be able to make these changes from any of them.
In Vue JS it was possible to do things like this...
const vueApp = new Vue({ el: "#vue-app", data(){
return { count: 1}
}})
setTimeout(() => { vueApp.count = 2 }, 1000)
I'm trying the same with Petite Vue but it does nothing.
// Petite Vue
const petiteVueApp = PetiteVue.createApp({
count: 0,
}).mount("#petite-vue");
setTimeout(() => { petiteVueApp.count = 2 }, 1000);
Logging the app gives just a directive and mount attribute, I can't find the count (nb if you log the above app it will show the count, because of that line petiteVueApp.count = 2, that isn't the data)
Demo:
https://codepen.io/EightArmsHQ/pen/YzemBVB
Can anyone shed any light on this?
There is an example which does exactly this in the docs which I overlooked.
https://github.com/vuejs/petite-vue#global-state-management
It requires an import of the #vue/reactivity which can be imported from the petite-vue bundle.
import { createApp, reactive } from 'https://unpkg.com/petite-vue?module'
setTimeout(() => { vueApp.count = 2 }, 1000)
const store = reactive({
count: 0,
inc() {
this.count++
}
})
createApp({
store
}).mount("#petite-vue")
setTimeout(() => { store.count = 2 }, 1000);
Updated working example:
https://codepen.io/EightArmsHQ/pen/ExEYYXQ
Interesting. Looking at the source code it seems that we would want it to return ctx.scope instead of return this.
Your workaround seems like the best choice if using petite-vue as given, or you could fork petite-vue and change that one line (I haven't tested this).

How to array destructure a Promise.all in Nuxt's asyncData

I am working with Nuxt and Vue, with MySQL database, all of which are new to me. I am transitioning out of WebMatrix, where I had a single Admin page for multiple tables, with dropdowns for selecting a particular option. On this page, I could elect to add, edit or delete the selected option, say a composer or music piece. Here is some code for just 2 of the tables (gets a runtime error of module build failed):
<script>
export default {
async asyncData(context) {
let [{arrangers}, {composers}] = await Promise.all([
context.$axios.get(`/api/arrangers`),
context.$axios.get(`/api/composers`),
])
const {arrangers} = await context.$axios.get('/api/arrangers')
const {composers} = await context.$axios.get('/api/composers')
return { arrangers, composers }
},
}
</script>
You do have the same variable name for both the input (left part of Promise.all) and as the result from your axios call, to avoid naming collision, you can rename the result and return this:
const { arrangers: fetchedArrangers } = await context.$axios.get('/api/arrangers')
const { composers: fetchedComposers } = await context.$axios.get('/api/composers')
return { fetchedArrangers, fetchedComposers }
EDIT, this is how I'd write it
async asyncData({ $axios }) {
const [posts, comments] = await Promise.all([
$axios.$get('https://jsonplaceholder.typicode.com/posts'),
$axios.$get('https://jsonplaceholder.typicode.com/comments'),
])
console.log('posts', posts)
console.log('comments', comments)
return { posts, comments }
},
When you destructure at the end of the result of a Promise.all, you need to destructure depending of the result that you'll get from the API. Usually, you do have data, so { arrangers } or { composers } will usually not work. Of course, it depends of your own API and if you return this type of data.
Since destructuring 2 data is not doable, it's better to simply use array destructuring. This way, it will return the object with a data array inside of it.
To directly have access to the data, you can use the $get shortcut, which comes handy in our case. Directly destructuring $axios is a nice to have too, will remove the dispensable context.
In my example, I've used JSONplaceholder to have a classic API behavior (especially the data part) but it can work like this with any API.
Here is the end result.
Also, this is what happens if you simply use this.$axios.get: you will have the famous data that you will need to access to later on (.data) at some point to only use the useful part of the API's response. That's why I do love the $get shortcut, goes to the point faster.
PS: all of this is possible because Promise.all preserve the order of the calls: https://stackoverflow.com/a/28066851/8816585
EDIT2: an example on how to make it more flexible could be
async asyncData({ $axios }) {
const urlEndpointsToFetchFrom = ['comments', 'photos', 'albums', 'todos', 'posts']
const allResponses = await Promise.all(
urlEndpointsToFetchFrom.map((url) => $axios.$get(`https://jsonplaceholder.typicode.com/${url}`)),
)
const [comments, photos, albums, todos, posts] = allResponses
return { comments, photos, albums, todos, posts }
},
Of course, preserving the order in the array destructuring is important. It's maybe doable in a dynamic way but I don't know how tbh.
Also, I cannot recommend enough to also try the fetch() hook alternative someday. I found it more flexible and it does have a nice $fetchState.pending helper, more here: https://nuxtjs.org/blog/understanding-how-fetch-works-in-nuxt-2-12/ and in the article on the bottom of the page.

Is there an easier way of updating nested arrays in react-native (react-redux)?

I am trying to update an array inside of my array (nested array) with react-redux. I found a solution to how to do this but is there any easier way of doing this rather than passing multiple parameter to the action.
[types.HISTORY_UPDATE](state, action){
return {
...state,
budgets: [
...state.budgets.slice(0,action.id),
{
key: action.key,
id: action.idd,
name: action.name,
budgetType: action.budgetType,
startDate: action.startDate,
currency: action.currency,
amount: action.amount,
amountLeft: action.amountLeft,
rollOver: action.rollOver,
color: action.color,
iconName: action.iconName,
history: [
...state.budgets[action.id].history.slice(0,action.histId),
{
note: action.note,
amount: action.amount,
type: action.type,
date: action.date,
fullDate: action.fullDate,
hours: action.hours,
min: action.min,
month: action.month,
year: action.year
},
...state.budgets[action.id].history.slice(action.histId+1)
]
},
...state.budgets.slice(action.id+1)
]
}
},
and the action goes like this
export function updateHistory(id,key,idd,name,budgetType,startDate,currency,amount,amountLeft,rollOver,color,iconName,histId,........){
I don't want to spend time with passing multiple parameter like this while using react-redux and also while I tried to run my application on my phone sometimes it really slows the application. Is it because of the example above?
I would be really appreciated If you guys come up with a solution.
I typically do not store arrays in redux, since updating a single element really is a burden as you noticed. If the objects you have inside your array all have a unique id, you can easily convert that array to an object of objects. As key for each object you take that id.
const convertToObject = (array) => {
let items = {};
array.map((item) => {
items[item.id] = item;
});
return items;
};
In your action you simply just pass the item you want to update as payload, and you can update the redux store very easily. In this example below I am just updating the budgets object, but the same logic applies when you assign a history object to each budget.
[types.BUDGET_UPDATE](state, action){
const item = action.payload;
return {
...state,
budgets: {
...state.budgets,
[item.id]: item
}
}
}
And if you want an array somewhere in your component code, you just convert the redux store object back to an array:
const array = Object.values(someReduxStoreObject);

Is it possible to call own Method in Vue data()?

So I'm using Element Vue, I need to get access to a method or to the value of the
acceptedDates
export default {
data() {
return {
acceptedDates: [],
pickerOptions1: {
disabledDate(time) {
return moment(time).isBetween(this.acceptedDates[0], this.acceptedDates[1]);
}
}
};
},
methods: {
//setting acceptedDates method...
}
I get a ReferenceError for this.accptedDates or even without using this. How do you do this?
Update
Thank you for the first anwsers, but I still can't figure it out.
I created this fiddle for you to see: https://jsfiddle.net/05nru5xq/13/
If you go to http://element.eleme.io/#/en-US/component/date-picker you will find that disabledDate is a Function in PickerOption.
Now that I know exactly what you are after, I've updated accordingly to your example https://jsfiddle.net/05nru5xq/31/
some points on your code:
never use capital to name methods, capital letter first is to name Object that can be created with the new attribute;
today is not a moment object so you can't call isBetween on it
from the docs you need to name your options as there's 3 of them, hence specifying the option :picker-options="{ disabledDate: betweenOneWeek }"
data is just a place to hold variables, don't put methods there.
As a side note:
I've done the same (bought it for me) and I'm not in any way affiliated with them, just a happy customer. If you want to know VueJs well enough and quick, try this Udemy course, it's pretty good and worth all the money
In the data section you can define variables with functions but you're not able to do things like you did. Why? It's simple. You're using this which binding to pickerOptions1 object, not data. Even when you use arrow function in object it won't work as well because in that case it will return window object.
Those operations on data you can move to separate function and in my opinion it would be the best way.
For example you can do something like that:
new Vue({
el: '#app',
data: {
message: 'Hello Vue.js!',
customMessage: 'Test ',
testFunction() {
this.customMessage += this.message;
alert(this.customMessage);
}
},
mounted() {
this.testFunction();
}
})
https://jsfiddle.net/mxuh7c9p/
or more suitable to your case:
new Vue({
el: '#app',
data: {
acceptedDates: [],
pickerOptions1: null,
},
methods: {
getDisabledDate(time) {
return moment(time).isBetween(this.acceptedDates[0], this.acceptedDates[1]);
},
setAcceptedDates() {
const disabledDate = this.getDisabledDate(time);
// do something
}
},
mounted() {
//this.getDisabledDate();
}
})
https://jsfiddle.net/mxuh7c9p/13/

ramda findIndex with gaps

I have the following code where I want to fill in the id, so I'm thinking to write something like this:
const data = [
{ id: 'some-id' },
{ id: 'some-other-id' },
{ id: 'third-id' },
];
const tabIndex = R.findIndex(R.propEq('id', R.__))(data);
So I can use it like this tabIndex('third-id'), but this is not a function.
What do I miss or confuse with this?
The following works
const tabIndex = (id) => R.findIndex(R.propEq('id', id))(data);
But I thought, that is the point of R.__ gaps function.
I think that by far the simplest way to do this is
const matchId = (id, data) => R.findIndex(R.propEq('id', id), data);
matchId('third-id', data); //=> 2
If you really want to make this points-free, Ramda offers several functions to help, such as useWith and converge (for which one can often substitute lift.) This one would take useWith:
const matchId = R.useWith(findIndex, [R.propEq('id'), R.identity]);
matchId('third-id', data); //=> 3
But I find the first version much more readable. You can find both on the Ramda REPL.
Do pay attention to the side note from Emissary. The R.__ placeholder is essentially used to show gaps between the arguments you supply; as a final argument it doesn't do anything.
I'm still trying to master this dark art myself but I think the issue is that R.findIndex expects a predicate (a function / assertion) as an argument and does not differentiate between predicates and regular curried functions as input.
To resolve this a new function can be composed (evaluated right to left):
const data = [
{ id: 'some-id' },
{ id: 'some-other-id' },
{ id: 'third-id' }
];
const tabIndex = R.compose(R.findIndex(R.__, data), R.propEq('id'));
console.log(tabIndex('third-id')); // 2
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.24.1/ramda.min.js"></script>
Side Note: the R.__ placeholder is inferred automatically for missing right-most arguments - e.g. R.propEq('id') and R.propEq('id', R.__) are equivalent.