Creating an Array of Likes from Javascript Functions - javascript

These are parts of my entire code. So what I am trying to do is create separate arrays of the values I like or dislike and output them in my html File onclick. I tried to create an empty array and push value but my final array ends up empty.
Script.js
const showRandomMovie = async() => {
const movieInfo = document.getElementById('movieInfo');
if (movieInfo.childNodes.length > 0) {
clearCurrentMovie();
};
const movies = await getMovies();
const randomMovie = getRandomMovie(movies);
const info = await getMovieInfo(randomMovie);
displayMovie(info);
};
playBtn.onclick = showRandomMovie;
helper.js
const displayMovie = (movieInfo) => {
const moviePosterDiv = document.getElementById('moviePoster');
const movieTextDiv = document.getElementById('movieText');
const likeBtn = document.getElementById('likeBtn');
const dislikeBtn = document.getElementById('dislikeBtn');
// Create HTML content containing movie info
const moviePoster = createMoviePoster(movieInfo.poster_path);
const titleHeader = createMovieTitle(movieInfo.title);
const overviewText = createMovieOverview(movieInfo.overview);
const releaseHeader = createReleaseDate(movieInfo.release_date)
// Append title, poster, and overview to page
moviePosterDiv.appendChild(moviePoster);
movieTextDiv.appendChild(titleHeader);
movieTextDiv.appendChild(overviewText);
movieTextDiv.appendChild(releaseHeader)
showBtns();
likeBtn.onclick = likeMovie;
dislikeBtn.onclick = dislikeMovie;
};
const likeMovie = () => {
clearCurrentMovie();
showRandomMovie();
};
// After disliking a movie, clears the current movie from the screen and gets another random movie
const dislikeMovie = () => {
clearCurrentMovie();
showRandomMovie();
};

Create arrays for the likes and dislikes and push it to an array. Pass it along to your methods.
likeBtn.onclick = () => rateMovie('likes', movieInfo);
dislikeBtn.onclick = () => rateMovie('dislikes', movieInfo);
have the method add it to the array
const ratings = {
likes: [],
dislikes: [],
};
const rateMovie = (type, data) => {
ratings[type].push(data);
clearCurrentMovie();
showRandomMovie();
};

Related

How to get each item from a filtered array, without using a map for each item

I'm taking an array and filtering the value in a context:
const { responsible } = useResponsible()
const [ids, setIds] = useState([])
const filteredResponsible = responsible?.filter((resp) =>
ids.includes(resp.id)
)
The problem is that I need to make a map to get the corresponding value of each id, one by one. This ends up making the code too long:
const { filteredResponsible } = useResponsible
const responsibleName = filteredResponsible.map((resp) => resp.name)
const responsibleEmail = filteredResponsible.map((resp) => resp.email)
const responsibleAddress = filteredResponsible.map((resp) => resp.address)
...
And so on with each item in the array.
I'm using the React Hook Form's setValue to set the value in the inputs:
useEffect(() => {
setValue('name', `${responsibleName}`)
setValue('email', `${responsibleEmail}`)
setValue('address', `${responsibleAddress}`)
setValue('cep', `${responsibleCep}`)
setValue('district', `${responsibleDistrict}`)
setValue('city', `${responsibleCity}`)
setValue('state', `${responsibleState}`)
setValue('phone', `${responsiblePhone}`)
setValue('sex', `${responsibleSex}`)
}, [])
How can I make these maps smaller? Without having to make a map to get each item in the array?
There doesn't seem to be any reason to do those map calls on every render and to do them anywhere other than where you need them, since you only show using the result in a mount-only effect. Just do them there:
const { filteredResponsible } = useResponsible; // Is there really no `()` needed here?
useEffect(() => {
setValue("name", `${filteredResponsible.map(({name}) => name)}`);
setValue("email", `${filteredResponsible.map(({email}) => email)}`);
setValue("address", `${filteredResponsible.map(({address}) => address)}`);
// ...
}, []);
If you really need those distinct arrays on every render, unless you can change your data structures to be more amenable to your output I don't see you have a lot of options. You can at least avoid multiple loops through filteredResponsible:
const { filteredResponsible } = useResponsible; // ()?
const responsibleName = [];
const responsibleEmail = [];
const responsibleAddress = [];
for (const { name, email, address } of filteredResponsible) {
responsibleName.push(name);
responsibleEmail.push(email);
responsibleAddress.push(address);
}
And if that's really the case, you may want to avoid doing it on every render:
const { filteredResponsible } = useResponsible; // ()?
const { responsibleName, responsibleEmail, responsibleAddress } = useMemo(() => {
const responsibleName = [];
const responsibleEmail = [];
const responsibleAddress = [];
for (const { name, email, address } of filteredResponsible) {
responsibleName.push(name);
responsibleEmail.push(email);
responsibleAddress.push(address);
}
return { responsibleName, responsibleEmail, responsibleAddress };
}, [filteredResponsible]);

Enabling multiple filters for a single array

in my application, there are two types of filters, category and country. However, I am not able to get them to be applied at the same time. For example, I only want the intersection of Category: SaaS + Country: Singapore.
Any advice?
const loadData = props.load
const [card, setCard] = useState(loadData)
const [searchPhrase, setSearchPhrase] = useState("")
const search = (event)=>{
const matchedUsers = loadData.filter((card)=>{
return card.title.toLowerCase().includes(event.target.value.toLowerCase())
})
setCard(matchedUsers)
setSearchPhrase(event.target.value)
}
const filterCountry = (event)=>{
const filteredCards = loadData.filter((card)=>{
return card.country.includes(event.target.value)
})
setCard(filteredCards)
}
const filterCat = (event)=>{
const filteredCards = loadData.filter((card)=>{
return card.cat.includes(event.target.value)
})
setCard(filteredCards)
}
You can change your filter condition to check if the value is in all your considered types
const result = yourData.filter(item => item.country.includes(YOURPHRASE) || item.cat.includes(YOURPHRASE))
you can pass the filtered array as a parameter to the filtering functions :
const search = (event)=>{
const matchedUsers = loadData.filter((card)=>{
return card.title.toLowerCase().includes(event.target.value.toLowerCase())
})
setSearchPhrase(event.target.value);
return matchedUsers
}
const filterCountry = (event,array)=>{
return array.filter((card) => card.country.includes(event.target.value);
}
const filterCat = (event,array)=>{
return array.filter((card) => card.cat.includes(event.target.value);
}
useEffect(() => {
let result = matchedUsers();
result = filterCountry(result);
result = filterCat(result);
setArrayToFilter(result);
}, [searchPhrase]);

Building an Object from fetch statement

I have some code that when you console.log it, it looks like the image below:
The code I am running is as follows:
onClick={() => {
const stream = fetch(
'https://lichess.org/api/games/user/neio',
{ headers: { Accept: 'application/x-ndjson' } }
);
const onMessage = obj => {
console.log('test', obj);
};
const onComplete = () =>
console.log('The stream has completed');
stream.then(readStream(onMessage)).then(onComplete);
}}
export const readStream = processLine => response => {
const stream = response.body.getReader();
const matcher = /\r?\n/;
const decoder = new TextDecoder();
let buf = '';
const loop = () =>
stream.read().then(({ done, value }) => {
if (done) {
if (buf.length > 0) processLine(JSON.parse(buf));
} else {
const chunk = decoder.decode(value, {
stream: true,
});
buf += chunk;
const parts = buf.split(matcher);
buf = parts.pop();
for (const i of parts) processLine(JSON.parse(i));
return loop();
}
});
return loop();
};
export default readStream;
What I am trying to do is build a parent object that contains all these individual rows of data.
I'm new at promises and fetch etc. So currently, I have no idea on how to build this parent object that contains each individual row.
Any suggestions?
Can't you have a global array and add items to it like:
var arrCollection = [];
...
const onMessage = obj => {
arrCollection.push(obj);
};
You can have an object with those items doing like:
var objCollection = { items: arrCollection };

Retrieve data from real time firebase in useEffect return undefined

I tried to implement the followers/following function and it succeeds but, I have a problem retrieving followers and following lists from real-time firebase.
When the user presses on another username followers/following, it sends the uid of the pressed user to this class, then by using the uid followers' list is retrieved and displayed.
The uid is correct at the beginning of the class, but the followers' list returns undefined and sometimes it returns a list on the second save(when I press Ctrl+s).
export default function showFollowers({
navigation,
route
}) {
const [followerslist, setFollowersList] = useState();
const [uid, setuid] = useState(route.params.uid);
const [usersList, setUsersList] = useState([]);
const followersl = [];
// ---snip---
}
HERE, the followers list returned undefined.
useEffect(
() => {
const usersRef1 = firebase.database()
.ref('users/' + uid)
.child("followers");
usersRef1.on('value', async (snapshot) => {
const users1 = snapshot.val();
//const followersl= [];
for (let id in users1) {
followersl.push(users1[id]);
}
await setFollowersList(followersl)
console.log(followerslist) // undefined
console.log(uid) // correct
});
},
[]
);
// Calling second to return info of each follower [profile image,username,name] to be displayed as flat list.
second;
const second = () => {
for (var i = 0; i < followerslist.length; i++) {
getInfo(followerslist[i]);
}
}
const getInfo = (element) => {
const usersRef = firebase.database()
.ref('users')
.orderByChild('usernameLC')
.equalTo(element.toString().toLowerCase());
usersRef.on('value', (snapshot) => {
const users = snapshot.val();
for (let id in users) {
usersList.push(users[id]);
}
setUsersList(usersList);
});
}

Add documentID of fetched document to array in firebase cloud function

I have a cloud function that "Joins" data from a list of documents in a collection.
I then return the result as an array, but I want to return the documentId as well (doc.id) in the list that i return.
How can i do that?
const restData = [];
//const userId = ctx.auth.uid;
const userId = 'dHAP1CNN6LhJWddQoTqyIkqIjhB2'; // !!! TEST ONLY
const all = await db.collection(`/customers/${userId}/lunch_cards`).listDocuments().then((snapshot) => {
snapshot.forEach(doc => {
const nextData = db.collection(`/restaurants`).doc(doc.id).get();
const newData = {...nextData, documentId: doc.id}; <-- This does not work only documentId isout in newData
console.log(util.inspect(newData));
restData.push(nextData);
console.log(doc.id);
});
});
const snaps = await Promise.all(restData);
const responseArray = snaps.map((s) => {return s.data()});
return responseArray;
I solved it!
Solution:
Just adding a new string to the array :)
const responseArray = snaps.map((s) => {
const snapData = s.data();
if (snapData) {
snapData['id'] = s.id;
}
return snapData;
});

Categories

Resources