Computed reverse() mix up in vue 3 ref array - javascript

I have simple messages array and when new message appear I need to push it to array:
const props = defineProps(['conversation'])
const messages = ref(props.conversation.messages) -> [{body: 'Something'}]
const filteredMessages = computed({
get () {
return messages.value.slice().reverse();
}
})
onMounted(() => {
messages.push({
body: 'Test 1'
})
})
For some reason, when I use .reverse() on array, it displays wrong body value [Something] on screen even tho in dev tools it has the right value [Test 1]. Without .reverse() the right value [Test 1] is displayed.
Anyone know why?

Related

fetch gives me a full array but it is empty when i try to access it

I get an object from a Symfony rest API. This object has a property "shooting" which is an array and this array is full when I console.log it but when i try to access it, it is empty
This is my fetch request
const getProjectsAvailable = async () => {
const data = await fetch(
`${process.env.GATSBY_CORE_URI}/api/dashboard/supplier/projects/available`,
{
headers: {
[`X-Auth-Token`]: `${token}`,
[`Accept`]: `application/json`,
},
}
);
return data;
};
Here is the project object that i get back from fetch request
0: {id: 258, name: "Project26-1", reference: "A6568", isOfferValidated: null, source: "dashboard", …}
It has a shooting key which contains an array and it is not empty
shootings: Array(1)
0:
addressCity: "Paris"
addressCountry: {id: 76}
But when i set this object to my component state, all values stay the same except the shooting key which becomes an empty array
const [projects, setProjects] = useState([]);
useEffect(() => {
getProjectsAvailable().then(res =>
res.json().then(data => {
setProjects(data);
})
);
}, []);
I have no idea why does it act like that.
Thanks in advance
EDIT :
For example, the first line with console.log gives me the response object with a full shooting array while the second one sets it to my state but shooting array is empty
useEffect(() => {
getProjectsAvailable().then(response => console.log(response));
getProjectsAvailable().then(response => setProjects(response));
}, []);
Ok it is my bad. Somewhere else in the code, there was a .split() on the shooting property which mutates the array so the props changed and shooting array got empty

mach beginning javascript with Array

Good afternoon, I am trying to make a method that tells me the number of elements an Array has that starts with "RT:"
For this I have developed the following code:
public getRowsRTs(idProyecto){
this.twitterService.getTargets().subscribe((data) => {
this.Twitter = data;
});
let countRT = this.Twitter.filter( tweet => tweet.message.startsWith("RT:")).length;
return countRT;
}
}
Here, data returns all the Documents that Mongo extracts, and puts them in the Twitter Array that I have defined at the beginning of the component. Within this Array each element has different attributes, such as _id, message, date ... I want you to tell me how many of those documents, the message value, begins with RT: and to return it to me, this code , it does not give me any problem, but it does not give me absolutely nothing, I do not know if someone could help me.
If the array is filled with strings, this should work:
let regixForRTStart = /^RT:/;
startArray = ['RT:1', 'RT:2', 'Other', 'Stuff'],
count = startArray.filter(item => regixForRTStart.test(item))
// length
console.log(count.length);
use filter and startsWith methods.
const arr = [
{ message: "abc" },
{ message: "RT:" },
{ message: "RT: 2" },
{ message: "test" }
];
const count = arr.filter(({ message }) => message.startsWith("RT:")).length;
console.log(count);

How to remove one item from an array using filter() in ReactJS - function not working properly

I have a function to delete a recipe object from an array of recipes objects.
I am actually able to delete a recipe (remove it from the array called recipeList), but when I hit one delete button, it removes ALL of the recipes in the array. I only want to remove the one that I am clicking on.
I am pretty sure it has something to do with this.state.id. It's coming up undefined when I console.log it. It should be referring to the key/id of the recipe being deleted.
Anyone have any ideas what the issue could be?
This is the delete function:
handleDeleteRecipe = recipeId => {
// copy current list of items
const recipeList = [...this.state.recipeList];
//filter out item being deleted
const filteredList = recipeList.filter(recipe => this.state.id !== recipeId);
this.setState({recipeList: filteredList});
console.log('id: ' + this.state.id);
}
In the initial state, id is inside of an object called newRecipe and it is set to empty:
this.state = {
recipeList: [],
newRecipe: {
title: '',
source: '',
servings: '',
id: ''
}
I have an add new recipe function where id is set to a random number between 1 and 1000. No idea if that would have anything to do with it. It is inside of the newRecipe object which then gets added to recipeList array.
handleAddNewRecipe = (title, source, servings, id) => {
const newRecipe = {
title: title,
source: source,
servings: servings,
id: (Math.floor(Math.random()* 1000))
This is where each recipe in the array gets mapped and returned as a Component. It has a key which is set to recipe.id.
{this.state.recipeList.map((recipe) => (
<RecipeCardThumbnail
title={recipe.title}
servings={recipe.servings}
key={recipe.id}
handleDeleteRecipe={this.handleDeleteRecipe}
/>
))}
This is the delete button from the child component:
onClick={() => this.props.handleDeleteRecipe(this.props.id)}>Delete</button>
There's obviously something I am not understanding but I am not sure what. Any help would be much appreciated!
EDIT: I also tried console.logging recipeList when I add my recipe to the array and the id showed up just fine. So I tried recipeList.id and the same issue occurred of all of the recipes getting removed.
EDIT AGAIN: I did an experiment and got rid of everything in the delete function except for the console.log. I tried logging recipeList and everything in the object was there. But when I logged recipeList.id or even recipeList.title they both showed up as undefined. I am still not sure what I am doing wrong though...
this.state.id will return undefined because you don't have id directly under your state.
try this
handleDeleteRecipe = recipeId => {
// copy current list of items
const recipeList = [...this.state.recipeList];
//filter out item being deleted
const filteredList = recipeList.filter(recipe => recipe.id !== recipeId);
this.setState({recipeList: filteredList});
Your filter looks wrong you are never using the recipe object that you are filtering on. I would assume it should be recipeList.filter(recipe => recipe.id !== recipeId)
Also, you do not need to copy the array first... Array.filter will return a new array anyway

Why am I getting back "undefined" from my Axios call, when it should return me objects?

Problem Intro:
In my React app I'm making some API calls to Github to fetch some user data. In another function I call these functions and wait for it with Axios's .all() method.
I want to fetch the data and do something with it using .then() but the returned value is just an array with 2 times undefined
What is the expected thing to happen:
It should return me 2 player objects with profile infos in the profile key of the object and a score value in the score key of the object.
What is my app doing in a nutshell?
It fetches the data from 2 usernames and they can "battle" each other. It just fetches the score and the followers and returns a sum. At the end it (should) returns an array with 2 player objects already sorted with the winner in the first place (exampleArray[0]).
General information's
It's an react app using components. It's really about one very tiny component and the helper functions in another file.
Here is where I call my custom function (the one returning undefined):
componentDidMount() {
const players = queryString.parse(this.props.location.search); //<== the usernames
const playersArray = [players.playerOneName, players.playerTwoName];
console.log(playersArray); // <== this logs the output as expected (an array with 2 usernames)
battle(playersArray).then((data) => { // <== the function it's all about
console.log(data); // <== data is => [undefined, undefined];
})
}
Next is the battle function from above that uses 2 other functions:
battle
export function battle(players) { // <== players aray with 2 usernames as string
return axios.all(players.map(getUserData)) // <== look 1 function below
.then(sortPlayers) // <== two functions below
.catch(handleError)
}
getUserData
let getUserData = (player) => {
axios.all([
getProfile(player),
getRepos(player)
]).then((data) => {
return {
profile: data[0],
score: calculateScore(data[0], data[1])
}
})
}
sortPlayers
let sortPlayers = (players) => {
return players.sort((a, b) => {
return b.score - a.score;
})
}
Ok so they also use other functions but they are really not too complicated. Let me know when you need examples from the other little helpers too.
I tried it with placing the debugger in different spots in the code and console logged different things, but I can't come through (first time I'm really working with promises). Sitting now 2 hours in front of this tiny problem and I can't figure it out.
I think the problem lies somewhere in battle function itself or getUserData
At the end a little screenshot, what the output of my console.log looks: http://prntscr.com/hz5abq
Thanks in advance
You don't have anything being returned in getUserData . Either add a return or remove the {} wrapping axios.all
let getUserData = (player) => {
return axios.all([
getProfile(player),
getRepos(player)
]).then((data) => {
return {
profile: data[0],
score: calculateScore(data[0], data[1])
}
})
}
getUserData needs to return the promise that it creates. At the moment it's not returning anything, so an implicit undefined is returned, and thus players.map(getUserData) results in an array of [undefined, undefined]
Ie, do this:
let getUserData = (player) => {
// VVV added return statement
return axios.all([
getProfile(player),
getRepos(player)
]).then((data) => {
return {
profile: data[0],
score: calculateScore(data[0], data[1])
}
})
}

#ngrx return one object from array with .single

I want to return an Observable of one object, selected from an array of objects from my store. I would like to use the .single operator, because this would throw an exception if there are less or more than 1 objects present. I can't get it to work though, because my store is returning an array instead of an observable. I know I could use .filter on the array, but I would like to understand why I can't get it to work. I even tried using a selector.
My App reducer has:
export interface AppState {
batStores: fromBatStores.State;
}
export const reducers: ActionReducerMap<AppState> = {
batStores: fromBatStores.batStoresReducer,
};
The reducer of my module:
export interface State {
batStores: BatStore[];
}
const initialState = {
batStores: [
new BatStore(0, 0, true, 'Cell 11', 11, 11),
new BatStore(1, 0, false, 'Cel 12', 12, 11),
new BatStore(2, 0, true, 'Cel 13', 13, 11),
new BatStore(2, 0, true, 'Cel 14', 14, 11),
]
};
export const selectBatStores = (state: fromApp.AppState) => state.batStores;
export const selectBatStoresBatStores = createSelector(selectBatStores, (state: State) => state.batStores);
Now I try something like this in my ngOnInit:
ngOnInit() {
const editId = 11;
const batStore$: Observable<BatStore> = this.store.select(fromBatStores.selectBatStoresBatStores)
.single(bs => bs.number === editId);
this.batStore$ = batStore$;
}
PhpStorm says the number property doesn't exist on BatStore[]. Which I don't understand, because at the example documentation single is also used as an operator on observable array.
Update
After reading the answers, still very confused. To test, I wrote my function like this:
getBatStore(id: number) {
const versionA$ = this.store.select(fromBatStores.selectBatStoresBatStores)
.switchMap((batStores: BatStore[]) => Observable.from(batStores))
.filter((bs: BatStore) => {
console.log('Analyzing ', bs);
console.log('Result ', bs.number === id);
return bs.number === id;
});
const versionB$ = this.store.select(fromBatStores.selectBatStoresBatStores)
.switchMap((batStores: BatStore[]) => Observable.from(batStores))
.single((bs: BatStore) => {
console.log('Analyzing ', bs);
console.log('Result ', bs.number === id);
return bs.number === id;
});
console.log('VersionA: ', versionA$);
console.log('VersionB: ', versionB$);
console.log('Same? ', versionA$ === versionB$);
return versionB$;
}
Both versions output the same thing to the console. VersionA works when using with async pipe in my view, VersionB doesn't. The code compiles and PhpStorm doesn't complain.
The select is getting a reference to the whole array and so the number property does not exist on it. Try a switchMap to switch to a new observable that expands the list so they can be selected one at a time like so:
const batStore$: Observable<BatStore> = this.store.select(fromBatStores.selectBatStoresBatStores)
.switchMap((batStores : BatStore[]) => Observable.from(batStores))
.single((bs: BatStore) => bs.number === editId);
I understand your confusion, PhpStorm is right to say "the number property doesn't exist on BatStore[]". The example documentation is also correct. The key here, in this example from RxJs, is you need to know how the Observable.from([array]) works. An Observable.from([array]) creates a "cold" observable that does one emission for every item in the array. So, the resulting Observable is of type number, not of type array, as you can see here:
const source: Observable<number> = Rx.Observable.from([1,2,3,4,5]);
The Observable that are you facing in your store, is an Observable of type Array. For example if you use the operator Observable.of, this will emit the array, not every item of the array:
const source: Observable<number[]> = Rx.Observable.of([1,2,3,4,5]);
Said that, I would do an Array.filter, for me it's better than any other transformation on the Observable stream.
Let me know if you have any doubt,
Hope this helps.
The select method will retorn an array object, for that reason you cant access the number property. You could try the following:
ngOnInit() {
const editId = 11;
this.batStore$ = this.store.select(fromBatStores.selectBatStoresBatStores)
.flatMap(list => list)// flat list to single elements, emit 1 value per element
.single(bs => bs.number === editId);
}
Another approach would be to store the elements in your state as key,value pairs and then either create a selector that takes the Id argument, or store that Id in the state and then compose 2 selectors (1 for collection of elements, 1 for Id) into one.

Categories

Resources