I'm just starting to learn JS. I need to redo this function into an explicit one. As a result, the property should be added to the object. And please explain how it works.
const newPost = (post, addedAt = Date()) => ({
...post,
addedAt,
})
const firstPost = {
id: 1,
name: 'Max'
}
console.dir(newPost(firstPost))
That's all I could think of. There are no further ideas
const firstPost = {
id: 1,
name: 'Bogdan'
}
const newPost = (addedAt = Date(), ...post) => {
return post
}
newPost(firstPost)
Related
I'm trying to use the same code below in React. I've tried a couple ways but it doesn't work the same way.
working old code (not react code)
const array = []
res = await getData()
res.data.forEach(item) => {
array.push({
...item,
isSelected: false,
id: getItemId(item.id)
})
not working new code (React)
const [array, setArray] = useState([])
const fetchItems = useCallback(async () => {
res = await getData()
const newData = res.data.forEach(item) => {
return [{...item, isSelected: false, id: getItemId(item.id) }]
})
setArray(newData)
}, [])
fetchItems()
console.log(array)
Is there a clean way to write this the same way it was done in the working code? Preferably without using push
try
const fetchItems = useCallback(async () => {
res = await getData()
const tempArr = res.data.map(item => ({...item, isSelected: false, id:
getItemId(item.id) }))
setArray(tempArr)
}, [setArray, getData, getItemId])
but make sure your functions getData, getItemId wont change by wrapping them with useCallback as well or avoid using useCallback.
In this change:
const newData = res.data.forEach(item) => {
What are you expecting forEach() to return and why? Taking a step back... You already have working code, so just use your known working code. Since the React component declares an array variable already, the only change you need to make is to rename your local variable:
const newArray = []
res = await getData()
res.data.forEach(item) => {
newArray.push({
...item,
isSelected: false,
id: getItemId(item.id)
})
})
Then just update state to your new array:
setArray(newArray);
Here is an approach:
const newData = res.data.map((item)=>{
return {
...item,
isSelected: false,
id: getItemId(item.id)
}
})
setArray(newData)
This will modify the value of the state .
Replace your Array.forEach to use Array.map. Because Array.forEach returns undefined but you expecting to have a new array.
I suppose that you should use useEffect rather than useCallback when fetching/editing data inside the component. In react you can write like this;
async function handleFetch() {
const res = await getData();
const newData = res.data.map((item) => {
return [{ ...item, isSelected: false, id: item.id }];
});
setArray(newData);
}
useEffect(() => {
handleFetch();
}, []);
to mock data I wrote this ;
function getData() {
return { data: [{ isSelected: true, id: 1 }] };
}
And you can check out stackblitz link
const form = await Form.findOne({ _id: res._id }).populate({
path: "activity.viewedBy",
model: User,
});
const a = await form.activity.map((a) => a.viewedBy);
console.log(a.map((e) => e.email));
"Cannot read property 'email' of undefined"
Why?
a is an array, full of objects, like this:
[
{
id: 123,
email: example#email.com
},
{
id: 456,
email: nice#email.com
}
]
Edit, sharing the whole async function:
const viewForm = async (req, res) => {
const form = await Form.findOne({ _id: res._id }).populate({
path: "activity.viewedBy",
model: User,
});
const a = await form.activity.map((a) => a.viewedBy);
console.log(a.map((e) => e.email));
await Form.updateOne(
{ _id: res._id },
{
$push: {
activity: {
viewedBy: res.user,
date: new Date(),
},
},
}
);
return {
statusCode: 200,
body: JSON.stringify(`Form viewed.`),
};
};
Edit2:
There was an undefined in the array, among the objects, I didn't notice that... That's why I was getting the undefined.
a probably has a different structure than you think (try console.log(a)), just proving:
const data = [
{
id: 123,
email: "example#email.com"
},
{
id: 456,
email: "nice#email.com"
}
];
const result = data.map((a) => a.email);
console.log(result);
Also, giving your variables meaningful names can help to prevent mistakes.
await form.activity.map((a) => a.viewedBy);
will return an array of viewedBy values. So the array a doesn't contain the full objects. Instead, it contains an array of viewedBy elements.
Also, please take a look at the functionality of the map() function.
When I run this code, I get an error of cannot read property 'map' of undefined.
I have tried moving around the functions, but the error persists.
const users = [{age: 45, height: 5.6, weight: 76, name:'David', country: 'Nigeria', id: '85eir7e0hj'}];
const select = document.querySelector('.select-text');
const bmiButton = document.querySelector('#oracle');
const getSelectedUser = (userId) => {
return user = users.find(({ id }) => userId === id);
};
const displaySelectedUser = ({ target }) => {
const user = getSelectedUser(target.value);
const properties = Object.keys(user);
properties.forEach((prop) => {
const el = document.querySelector(`[data-${prop}-value]`);
if(el !== null) el.textContent = user[prop];
})
};
const letsCalculateBMI = () => {
};
const powerupTheUI = () => {
select.addEventListener('change', displaySelectedUser);
bmiButton.addEventListener('click', letsCalculateBMI)
}
const displayUsers = (users) => {
users.forEach((user) => {
const opt = document.createElement('option');
opt.value = user.id;
opt.textContent = user.name;
select.appendChild(opt);
})
}
const fetchAndDisplayUsers = () => {
users.push({
age: 40,
weight: 75,
height: 6,
country: 'Nigeria',
name: 'Charles Odili',
id: 'dfhb454768DghtF'
});
displayUsers(users);
};
const startApp = () => {
powerupTheUI();
fetchAndDisplayUsers();
};
startApp();
Something is retrieving the .map attribute from a null variable. It is not anything in the presented code: as comments noted, there is no map in your code.
Indeed, your code appears to run correctly by itself. I opened a random webpage, changed one HTML element to class="select-text" and another to id="oracle", and pasted your code into the console. Clicking on the #oracle element caused data from your object to be added to the .select-text.
If you cannot get the line/source of the error, try the following (one at a time):
running the code on another page without whatever other JavaScript may be running on the original,
adding logging statements throughout your code (to see where other code may be executing and interfering), and
disabling browser extensions, changing browsers, otherwise eliminating other factors that could be affecting your environment.
I'm trying to access a data object that is referenced by a key. In this case, we have "applicant" data nested within an Event. I'm trying to create a new object with that data. I can access top-level Event data and the key for each applicant, but I can't figure out how to access applicant data - for example, application date, notes, and status.
I'd like to say something like applicationStatus = key.status, but that doesn't work.
onCreateApplication () {
fb.eventsCollection.orderBy('startDate', 'desc').onSnapshot(querySnapshot => {
let appsArray = []
querySnapshot.forEach(doc => {
let event = doc.data()
let eventId = doc.data().id
let eventTitle = doc.data().title
let eventSlug = doc.data().slug
let applications = doc.data().applicants
let appStatus = doc.data().applicants.status
for (var key in doc.data().applicants) {
let eventData = {
id: eventId,
title: eventTitle,
slug: eventSlug
}
let userData = {
id: key
}
let application = {
event: eventData,
user: userData,
status: key.status????????,
appliedDate: key.created??????
}
fb.applicationsCollection.add(application)
}
})
})
},
This is my best guess as to what is going on with your data structure. I hope this helps and please comment to clarify anything else.
onCreateApplication(){
fb.eventsCollection.orderBy('startDate', 'desc').onSnapshot(querySnapshot => {
querySnapshot.forEach(doc => {
let data = doc.data();
let applications = Object.keys(data.applicants).map(function(id){
let application = {
event: {
id: data.id,
title: data.title,
slug: data.slug
},
user: {
id: id
},
status: data.applicants[id].status,
appliedDate: data.applicants[id].created
})
fb.applicationsCollection.add(application);
return application;
})
})
})
}
I’m new to reactive programming and toying around with cycle.js, trying to implement who to follow box from this tutorial. But I understood that for proper implementation (and learning purposes) I don’t have one piece of data: full user name. I can get it by sequentially getting users and then full user data from server. In imperative style I would do something like this:
fetch(`https://api.github.com/users`)
.then(data => data.json())
.then(users => fetch(users[0].url))
.then(data => data.json())
.then(/* ... work with data ... */)
But how do I do it in cycle?
I’m using fetch driver and trying something like this:
function main({ DOM, HTTP }) {
const users = `https://api.github.com/users`;
const refresh$ = DOM.select(`.refresh`).events(`click`)
const response$ = getJSON({ key: `users` }, HTTP)
const userUrl$ = response$
.map(users => ({
url: R.prop(`url`, R.head(users)),
key: `user`,
}))
.startWith(null)
const request$ = refresh$
.startWith(`initial`)
.map(_ => ({
url: `${users}?since=${random(500)}`,
key: `users`,
}))
.merge(userUrl$)
const dom$ = ...
return {
DOM: dom$,
HTTP: request$,
};
}
where getJSON is
function getJSON(by, requests$) {
const type = capitalize(firstKey(by));
return requests$
[`by${type}`](firstVal(by))
.mergeAll()
.flatMap(res => res.json());
And I’m always getting some cryptic (for me) error like: TypeError: Already read. What does it mean and how do I handle it properly?
You were quite close. You just need to remove startWith(null) as a request, and grabbing the second response (you were missing the getJSON for that one).
function main({ DOM, HTTP }) {
const usersAPIPath = `https://api.github.com/users`;
const refresh$ = DOM.select(`.refresh`).events(`click`);
const userResponse$ = getJSON({ key: `user` }, HTTP);
const listResponse$ = getJSON({ key: `users` }, HTTP);
const userRequest$ = listResponse$
.map(users => ({
url: R.prop(`url`, R.head(users)),
key: `user`,
}));
const listRequest$ = refresh$
.startWith(`initial`)
.map(_ => ({
url: `${usersAPIPath}?since=${Math.round(Math.random()*500)}`,
key: `users`,
}));
const dom$ = userResponse$.map(res => h('div', JSON.stringify(res)));
return {
DOM: dom$,
HTTP: listRequest$.merge(userRequest$),
};
}
Because inquiring minds want to know...here's a complete working example:
import Cycle from '#cycle/rx-run';
import {div, button, makeDOMDriver} from '#cycle/dom';
import {makeFetchDriver} from '#cycle/fetch';
import R from 'ramda'
function main({DOM, HTTP}) {
const usersAPIPath = 'https://api.github.com/users';
const refresh$ = DOM.select('button').events('click');
const userResponse$ = getJSON({ key: 'user' }, HTTP);
const listResponse$ = getJSON({ key: 'users' }, HTTP);
const userRequest$ = listResponse$
.map(users => ({
url: R.prop('url', R.head(users)),
key: 'user',
}));
const listRequest$ = refresh$
.startWith('initial')
.map(_ => ({
url: `${usersAPIPath}?since=${Math.round(Math.random()*500)}`,
key: 'users',
}));
const dom$ = userResponse$.map(res => div([
button('Refresh'),
div(JSON.stringify(res))
]));
return {
DOM: dom$,
HTTP: listRequest$.merge(userRequest$)
};
function getJSON(by, requests$) {
return requests$.byKey(by.key)
.mergeAll()
.flatMap(res => res.json());
}
}
Cycle.run(main, {
DOM: makeDOMDriver('#main-container'),
HTTP: makeFetchDriver()
});
It took me a while to figure out HTTP was the #cycle/fetch driver, and NOT the #cycle/http driver. Next, a bit of searching turned the ramda npm library providing prop and head methods.