Adding an Audio object to my react state array - html

componentWillMount() {
console.log('Component WILL MOUNT!')
axios.get('/channels').then( (res) => {
console.log(res.data.data.playList);
this.setState({
categories: res.data.data.playList,
audioList: res.data.data.playList.url
})
}).catch( (err) => {
console.log(err);
});
}
In my componentWillMount() I get bunch of mp3 urls from a database and stores into a state called audioList so it has a bunch of URLs of a sound file. However, what I actually want to store is an Audio object (HTML5 Audio).
Usually, to make it playable, I would have to make a new Audio object like
this.audio = new Audio([URL]);
then do
this.audio.play()
Since I want to make a list of music, I would like to but everything like
this.state.audioList = [ audioObject1, audioObject2, audioObject3, ... ]
How can I do this?
EDIT
componentWillMount() {
console.log('Component WILL MOUNT!')
let playLists = [];
axios.get('/channels').then( (res) => {
//console.log(res.data.data.playList);
res.data.data.playList.map((value, key) => playLists.push(new Audio(value.url)));
this.setState((prevState) => {
return { audioList: playLists}
}, () => console.log("dddd" + this.state.audioList));
}).catch( (err) => {
console.log(err);
});
}
This gives me
EDIT2
componentWillMount() {
console.log('Component WILL MOUNT!')
let playLists = [];
axios.get('/channels').then( (res) => {
//console.log(res.data.data.playList);
res.data.data.playList.map((value, key) => playLists.push(new Audio(value.url)));
this.setState((prevState) => {
return { audioList: playLists, categories: res.data.data.playList}
});
}).catch( (err) => {
console.log(err);
});
}

You can try with array push like below for objects available inside array,
let playlists = [];
res.data.data.playList.map((value, key) => playlists.push(new Audio(value.url)));
this.setState((prevState) => {
return { audioList: playlists}
}, () => console.log(this.state.audioList));

Related

Asynch problem when fetching MySQL and EXPRESS

I'm trying to simple add a new property in an object. The array of objs is being fetched from my database and then I try to add a property which is also fetched from my database. Although when I try to manipulate it I'm receiving "undefined".
Is it indeed an asynch problem?
Am I doing any silly mistakes?
Those are questions that surrounds my head at the moment.
Code:
exports.getIndex = (req, res, next) => {
Report.fetchAll().then(([rows, fieldData]) => {
// console.log(rows);
const modifiedRows = rows.map(el => {
Report.fetchUserNameOfReport(el.UserInfo_idPessoa).then(([rows, fieldData]) => {
console.log(rows);
return {
...el,
userOfReport: 'Joao' //change later to smthing like rows.name
};
}).catch(err => console.log(err));
// return{
// ...el,
// userOfReport: 'Joao'
// };
});
res.render('user/index', { reports: rows, pageTitle: 'Social Reporter', path: '/' });
}).catch(err => console.log(err));
};
Obs This works if comment this out and comment Report.fetchUserNameOfReport function->
// return{
// ...el,
// userOfReport: 'Joao'
// };
Expected result:
{
idComplaint: 83059,
title: '4444',
description: '4444',
image: '4444',
location: '4444',
UserInfo_idPessoa: 80068,
userOfReport: 'Joao'
}
Actual result:
undefined
Thank you in advance!
You never return anything in your .map, so all of the values of modifiedRows will be undefined. You can map them all to promises to get all the values, and then access the modified rows once you wait for all of the promises to resolve. Also, you're shadowing your variable by declaring rows and fieldData multiple times:
exports.getIndex = (req, res, next) => {
Report.fetchAll().then(([rows, fieldData]) => {
// console.log(rows);
const modifiedRowPromises = rows.map(el => {
return Report.fetchUserNameOfReport(el.UserInfo_idPessoa).then(([rows2, fieldData2]) => {
console.log(rows2);
return {
...el,
userOfReport: 'Joao' //change later to smthing like rows2.name
};
});
});
Promise.all(modifiedRowPromises).then(modifiedRows => {
res.render('user/index', { reports: modifiedRows, pageTitle: 'Social Reporter', path: '/' });
}).catch(console.log);
}).catch(err => console.log(err));
};
Alternatively, if you use async/await syntax, this can be achieved much more cleanly:
exports.getIndex = async (req, res, next) => {
try {
const [rows, fieldData] = Report.fetchAll();
const modifiedRowPromises = rows.map(async el => {
const [rows2, fieldData2] = await Report.fetchUserNameOfReport(el.UserInfo_idPessoa);
return {
...el,
userOfReport: 'Joao' //change later to smthing like rows2.name
};
});
const modifiedRows = await Promise.all(modifiedRowPromises);
res.render('user/index', { reports: modifiedRows, pageTitle: 'Social Reporter', path: '/' };
} catch (err) {
console.log(err);
}
};

How could I pass JSON object array result to my api URL? (In REACT)

I have to fetch 2 api from backend, and try to get the result from this two. but, at the moment, the JSON result I get from the first API is object Array in JSON. I need to pass the id from first API(using setState) to second API for path variables. But when I do in my way, it fail to retrieve the data. Consider the code below:
componentDidMount(){
// console.log(loginEmail)
fetch(`http://localhost:9000/api/item/list`,)
.then((resp)=>{
resp.json().then((res)=>{
console.log(res.data);
// localStorage.setItem('id', res.data.user_info.id);
this.setState({data: res.data});
}
)
})
const id = this.state.data.id;
fetch(`http://localhost:9000/api/item/photo/view/${id}`,)
.then((resp)=>{
resp.json().then((res)=>{
console.log(res);
// localStorage.setItem('id', res.data.user_info.id);
this.setState({res});}
)
})
}
The problem is that fetch returns a Promise so, at the line
const id = this.state.data.id;
You do not have data populated yet.
You have to concatenate the two requests in a way like the following:
componentDidMount() {
fetch(`http://localhost:9000/api/item/list`)
.then((resp) => {
// return the id
})
.then((id) => {
fetch(`http://localhost:9000/api/item/photo/view/${id}`)
.then((resp) => {
// do what you need with the result
})
})
}
Fetch is asynchronous, which means javascript will
fetch data on the first call with no waiting, and continue
to the second fetch call where the id is not defined or Null.
In order to fix that you can use promises as follow
My code example
import React from "react";
class Home extends React.Component {
constructor() {
super();
this.state = {
res: [],
}
}
// http://jsonplaceholder.typicode.com/users
fetchData(url) {
return new Promise((resolve, reject) => {
fetch(url)
.then((resp) => {
resp.json().then((res) => {
console.log(res);
// localStorage.setItem('id', res.data.user_info.id);
resolve(res);
}
)
})
})
}
async componentDidMount() {
let data = await this.fetchData("http://jsonplaceholder.typicode.com/users");
console.log("data :", data);
let id = data[0].id;
console.log("Id :", id);
let newData = await this.fetchData(`http://jsonplaceholder.typicode.com/users/${id}`);
this.setState({ res: newData });
}
render() {
return (
<div>
Call API
</div>
)
}
}
export default Home
Adapted on your code
fetchData(url) {
return new Promise((resolve, reject) => {
fetch(url)
.then((resp) => {
resp.json().then((res) => {
console.log(res.data);
// localStorage.setItem('id', res.data.user_info.id);
resolve(res.data);
}
)
})
})
}
async componentDidMount() {
// console.log(loginEmail)
let data = await this.fetchData("http://localhost:9000/api/item/list");
let id = data.id;
let newData = await this.fetchData(`http://localhost:9000/api/item/photo/view/${id}`);
this.setState({ res: newData });
}
You need to make sure that each id gets its relevant results.
async componentDidMount() {
await fetch(`http://localhost:9000/api/item/list`)
.then(async (resp) => {
let req_ = resp.map((item)=>{
return await fetch(`http://localhost:9000/api/item/photo/view/${item.id}`)
})
let result = Promise.all(req_)
console.log(result)
})
}

What's the best way to mock a nested function?

consider a function
exports.projectNotifyLaunch = (admin, functions) => {
return functions.database.ref("/projects/{pid}").onCreate(snap => {
const { title } = snap.val();
const notification = {
title: `${title} just launched!`,
body: `We just heard about a new cryptocurrency project called ${title}`
};
return admin.messaging().sendToTopic("premium", { notification });
});
};
How should I mock deeply nested functions such as
functions.database.ref("/projects/{pid}").onCreate(snap => {});
or
admin.messaging().sendToTopic("premium", { notification });
in Jest? I want to fire off the snap=>{} callback and assert against the value of notification.
I was able to make this work
This works but it's quite verbose. I'm wondering if there is a better way, or a type of testing I'm not aware of with Jest.
describe("send notification to premium users on new project", () => {
// INPUTS
const snap = {
val: () => ({
title: "Test Title"
})
};
const functions = {
database: {
ref: () => ({
onCreate: callback => callback(snap)
})
}
};
// outputs
let topicStub = null;
let notificationStub = null;
const admin = {
messaging: () => ({
sendToTopic: (topic, notification) => {
topicStub = topic;
notificationStub = notification;
}
})
};
projectNotifyLaunch(admin, functions);
test("title is correct", () => {
expect(notificationStub.notification.title).toBe(
"Test Title just launched!"
);
});
test("topic is premium", () => {
expect(topicStub).toBe("premium");
});
});

React-Native render json from fetch

I have a fetch returning on ComponentDidMount(). Trying to get the response to render on the page.
I have set the state as follows:
this.state = {
loading: true,
file: null,
video: null,
marks: []
};
and my fetch:
componentDidMount() {
return fetch('http://10.0.2.2:8080/marks/createMark')
.then(response => response.json())
.then((data) => {
this.setState({
loading: false,
marks: data.mark
}, () => {
console.log(data.mark);
console.log(this.state.marks);
// const dataMap = data.mark.map((item) => {
// return {
// key: item.id,
// label: item.mark
// };
// });
});
})
.catch(err => console.log(err));
}
Now my render inside of the return:
const { marks } = this.state;
<FlatList
data={marks}
renderItem={({ item }) => <Text>{item.mark}</Text>}
keyExtractor={(item, index) => index}
/>
Do I have to map the data then try to render it??
OUTPUT OF console.log(this.state.marks):
{ _id: '5b61e47a55a0000aa980fab1', mark: 'ItHe', __v: 0 }
The mark is a pseudorandom string that can contain letters and numbers created on the backend
As this.state.marks is an object. First, you need to convert it to this form [{}]. You can do the following changes to make it work.
fetch('http://10.0.2.2:8080/marks/createMark')
.then(response => response.json())
.then((data) => {
let marks = [data.mark]; //Add this line
this.setState({
loading: false,
marks: marks // Change this line
}, () => {
....
Rest of your code
marks is an array but you're not sharing what each object in the array looks like. If it's an array of strings, you're good but if it's an object, you'll need to destructure it and pull out the string you're looking to render.
<Text>{item.mark.someKeyWhoseValueIsAString}</Text

Ionic 2 - Passing ID from json to child (details) page

I have a provider service that calls get requests from my API. I then have a listing page whereby you can scroll though many recipes. What I am struggling with is taking the ID of each recipe and passing it to the details page as this needs to be included within.
My service request is for the listing is
loadCategory1() {
var url = "http://api.yummly.com/v1/api/recipes?_app_id=////&_app_key=////";
if (this.Category1) {
return Promise.resolve(this.Category1);
}
return new Promise(resolve => {
this.http.get(url + "&allowedAllergy[]=396^Dairy-Free&allowedAllergy[]=393^Gluten-Free&maxResult=50&start=10")
.map(res => res.json())
.subscribe(data => {
console.log(data);
this.Category1 = data.matches;
resolve(this.Category1);
});
});
}
and I currently have a separate one for my details as well
loadDetails() {
if (this.details) {
return Promise.resolve(this.details);
}
return new Promise(resolve => {
this.http.get('http://api.yummly.com/v1/api/recipe/French-Onion-Soup-The-Pioneer-Woman-Cooks-_-Ree-Drummond-41364?_app_id=//////&_app_key=//////')
.map(res => res.json())
.subscribe(data => {
console.log(data);
this.details = data;
resolve(this.details);
});
});
}
As you can see in the details request i have French-Onion-Soup-The-Pioneer-Woman-Cooks-_-Ree-Drummond-41364 This needs to be dynamic by taking the ID from each recipe. Example is below.
Within each .ts file I have the following
loadRecipes(){
this.apiAuthentication.loadCategory1()
.then(data => {
this.api = data;
});
}
This allows me to call the request.
I'm at the point now where I have no clue what to do so some help would be great.
Your DetailsService can be something like this:
loadDetails(detailsId: string) {
return new Promise(resolve => {
this.http.get('http://api.yummly.com/v1/api/recipe/'+detailsId+'?_app_id=//////&_app_key=//////')
.map(res => res.json())
.subscribe(data => {
console.log(data);
this.details = data;
resolve(this.details);
});
});
}
Navigate to DetailsPage with arguments:
this.navCtrl.push(DetailsPage,{
recipe: recipe
});
And you can call DetailsService inside DetailsPage by using code like this:
loadDetails(){
this.apiAuthentication.loadDetails(this.recipe.id)
.then(data => {
this.details = data;
});
}