Fetching video array from cloudinary on React app - arrays

I have React web app with video hosting by cloudinary. I want to know the methods for pulling a random video from cloudinary library or making array? Database used is mongodb.
Here is code from VideoPlayer Component. I get React Error 152 when I try to run.
export default class VideoPlayer extends React.Component {
state = {
randomId: ''
};
componentDidMount() {
this.randomId();
}
randomId = () => {
axios
.get(inDev ? devAPI.concat("v2/getRandomId") : baseAPI.concat("v2/getRandomId"))
.then(data => this.setState({ randomId: data }))
.catch(err => {
console.log(err);
return null;
});
};
render() {
return(
<div>
{this.state.randomId.length === 0 ? (
<div>Loading...</div>
) : (
<div>this.state.randomId</div>
)}
</div>
)
}
}
Here is API
router.get("/v2/getRandomId", (req, res) => {
cloudinary.search.max_results(1).execute().then(result=>{
return res.json({
success: true,
data: result.resources
});
});
});
Thanks

I ended up creating a random number generator then assigning product of that variable to the Index value of video array carousel to shuffle videos on every page load. Random number generator was placed in componentWillMount Method to occur on every page load.
Thank you for all the help.

Related

onClick like button likes all objects in array React JS

I'm super new to web development but I'm trying to implement a like button to an API array of the mars rover images in react js. The problem I'm having is when I click the like button for one of my images all of the like buttons click. I've tried using id's, classNames, and keys for my button but nothing seems to be working. Any help would be appreciated :)
class Rover extends React.Component {
state = {
loading: true,
images: [],
};
async componentDidMount() {
const url = 'https://api.nasa.gov/mars-photos/api/v1/rovers/curiosity/photos?sol=1000&page=2&api_key='
const response = await fetch(url);
const data= await response.json();
this.setState({ images: data.photos, loading: false });
console.log(this.state);
}
render() {
if (this.state.loading) {
return <div>loading...</div>;
}
if (!this.state.images) {
return <div>didn't find image</div>
}
return (
<IconContext.Provider value={{ color: '#a9b3c1', size: 64 }}>
<RoverSection>
<RoverWrapper>
<RoverHeading>Mars Rover</RoverHeading>
<div>
{this.state.images.map((image, idx) => (
<div className={`some-image-${idx}`} key={`some-image${idx}`}>
<RoverContainer>
<RoverCard to='/'>
<RoverCardInfo>
<RoverCardID>Photo ID: {image.id}</RoverCardID>
<RoverCardFeatures>
<Img src={image.img_src} />
<RoverCardFeature>{image.rover.name} Rover</RoverCardFeature>
<RoverCardFeature>{image.camera.full_name}</RoverCardFeature>
<RoverCardFeature>{image.earth_date}</RoverCardFeature>
</RoverCardFeatures>
<Button primary id={image.id} className={`some-button-${idx}`} onClick={() => {
this.setState({
isLiked: !this.state.isLiked
})
}}>{this.state.isLiked ? <FaHeart/> : <FaRegHeart/>}</Button>
</RoverCardInfo>
</RoverCard>
</RoverContainer>
</div>
))}
</div>
</RoverWrapper>
</RoverSection>
</IconContext.Provider>
);
}
}
export default Rover
You are mapping through all of the images (you have an array of images); However, you do not have an array for your likes you just have a single boolean value. You need to create an array for your likes of equal size to your image array and then use the same index (you can get the current index in your map (you already did an named it idx))
Your initial like state should be similar to:
async componentDidMount() {
const url = 'https://api.nasa.gov/mars-photos/api/v1/rovers/curiosity/photos?sol=1000&page=2&api_key='
const response = await fetch(url);
const data= await response.json();
this.setState({ images: data.photos, isLiked:new Array(data.photos.length).fill(false), loading: false });
console.log(this.state);
}
and then in you component
this.setState((current)=>{
const newState={...current};
const isLiked = newState.isLiked;
isLiked[idx] = !isLiked[idx];
return {
...newState,
isLiked:[...isLiked]
}
})
and
{this.state.isLiked[idx] ? <FaHeart/> : <FaRegHeart/>}
lets say this is your image array:
this.state.images = [{id : 0, img : "img1"} ,{id : 1 , img : "img2"} ,{id : 2, img : "img3"} ]
now say you want to like img1 , when you click like on img1, dont you think that you need to only save img1 as liked image. you can do it by modifying the images array object. if you dont want to change data in your original image object,you can keep another array/object map with id and their like status ( you can keep all or you can only push the liked ones.
now when you click on any like button on image , call the function ( also bind it in constructor)
onClick = {(e)=> {this.handleLikeClick(image)}}
and in function handleLikeClick
handleLikeClick(image){
let copyImages = [...this.state.images]
this.state.images.forEach((img) => {
if(img.id === image.id) {
img.liked= !img.liked;
}
});
this.setState({
images :copyImages
})
}
now whenever you are in render , instead of just checking isLIked, you can check the liked property in image object.

how to add cookies so that a loader will only show up once a day

class Main extends Component {
state = {
loading: true
}
componentDidMount = () => {
setTimeout(() => {
this.setState({
loading: false
})
}, 1500)
}
render() {
return (
this.state.loading ?
<LoadingScreen></LoadingScreen>
:
<OptionScreen></OptionScreen>
)
}
}
I want the loading screen to only show up only once a day (refreshes after a day).
teammate told me to use cookies but I'm not sure
help please?????
Cookie is not feasible.
You can call "setInterval" or "setTimeout" to refresh the current page: window.location.reload(false);

Google Apps Script & React.js : DELETE https://mygoogleappapi.com/exec 405 (Method Not Allowed)

Thank you for reading!
I am learning how to use GAS now,
I can't delete the specific row I selected on google spread sheet.
I got the theme error after trying to delete using "axios.delete method" when I used react app and google script api.
I already passed GET method and POST method using axios. Actually , I could get and post my data from my google spread sheet.
but deleting could not access well.
I found this error 405 is not allowed to access my google sheet, but Why can I get this error even though the post method was accessible?
My App script or My react.js code need to have any code else ? I can't solve this problem...
I want to solve this error and delete the specific row I selected. Also, I want to know a workaround for this error.
Do you have any idea ? If you have some good idea,Could you tell me please ?
Thank you for reading.
this is my App script code.
function doDelete(req, sheet) {
var id = req.parameter.id;
var Row = sheet.getLastRow();
for (var i = 1; i <= Row; i++) {
var idTemp = sheet.getRange(i, 1).getValue();
if (idTemp == id) {
sheet.deleteRow(i);
}
}
}
this is my reactjs code.
import React,{ useState , Component } from 'react';
import Paper from '#material-ui/core/Paper';
import Grid from '#material-ui/core/Grid';
import axios from 'axios';
axios.defaults.baseURL = 'http://localhost:3000';
var optionAxios = {
headers: {
'Content-Type': 'application/json;charset=utf-8',
'Access-Control-Allow-Origin':'*' ,
}
}
const api = 'https://mygoogleappscriptapi.com/exec';
class Price extends Component {
constructor(){
super();
this.state = {
info: []
};
this.getInfo();
this.createInfo = this.createInfo.bind(this);
this.deleteInfo = this.deleteInfo.bind(this);
};
// accessed get!
getInfo = () =>{
axios.get(api)
.then((res) =>{
console.log(res.data)
this.setState({
info: res.data
})
})
}
// accessed post!
createInfo = () =>{
axios.post(api,{
product: "hoge",
price: 1000,
miniLot: 1000,
cartonSize: "40*30*50"
},optionAxios)
.then((res) => {
this.getInfo(res);
})
}
// cant't access delete!
deleteInfo = (e) => {
console.log(e);
axios.delete(api,{
id: e,
},optionAxios)
.then((res) =>{
this.getInfo(res);
console.log('success!');
})
}
render(){
return (
<div className={this.root}>
<Grid container>
<Grid item xs={11}>
<button onClick={this.createInfo}>createButon</button>
<Paper>
{this.state.info.map(info => <div key={info.id}>
{info.product}
<button onClick={() => this.deleteInfo(info.id)}>×</button>
</div>)}
</Paper>
</Grid>
</Grid>
</div>
);
}
}
export default Price;
Only the following HTTP methods are supported:
POST
GET
DELETE method is not supported by google-apps-script-web-application.
You can use post:
Server side:
function doPost(e){
if(e.parameter.option === "DELETE") return doDelete(e);
/*rest of doPost here*/
}
React:
// convert to axios.post
deleteInfo = (e) => {
console.log(e);
axios.post(api,{//modified
id: e,
option: "DELETE",//added
},optionAxios)
.then((res) =>{
this.getInfo(res);
console.log('success!');
})
}
Try this:
function doDelete(req, sh) {
var id = req.parameter.id;
const ss=SpreadsheetApp.getActive();
sh=sh||ss.getActiveSheet();
var vs=sh.getRange(1,1,sh.getLastRow(),1).getValues();
var d=0;
for (var i=0;i<vs.length;i++) {
if (vs[i][0]== id) {
sh.deleteRow(i+1-d++);
}
}
}

React - Render happening before data is returned and not updating component

I can't get this to work correctly after several hours.
When creating a component that needs data from Firebase to display, the data is returning after all actions have taken place so my component isn't showing until pressing the button again which renders again and shows correctly.
Currently my function is finishing before setState, and setState is happening before the data returns.
I can get setState to happen when the data is returned by using the callback on setState but the component would have already rendered.
How do i get the component to render after the data has returned?
Or what would the correct approach be?
class CoffeeList extends Component {
constructor(props) {
super(props);
this.state = {
coffeeList: [],
}
}
componentDidMount() {
this.GetCoffeeList()
}
GetCoffeeList() {
var cups = []
coffeeCollection.get().then((querySnapshot) => {
querySnapshot.forEach(function (doc) {
cups.push({ name: doc.id})
});
console.log('Updating state')
console.log(cups)
})
this.setState({ coffeeList: cups })
console.log('End GetCoffeeList')
}
render() {
const coffeeCups = this.state.coffeeList;
console.log("Rendering component")
return (
<div className="coffee">
<p> This is the Coffee Component</p>
{coffeeCups.map((c) => {
return (
<CoffeeBox name={c.name} />
)
})}
</div >
)
}
}
Thanks
The problem is that you set the state before the promise is resolved. Change the code in the following way:
GetCoffeeList() {
coffeeCollection.get().then((querySnapshot) => {
const cups = []
querySnapshot.forEach(function (doc) {
cups.push({ name: doc.id})
});
console.log('Updating state')
console.log(cups)
this.setState({ coffeeList: cups })
console.log('End GetCoffeeList')
})
}

ReactJS+FireStore Data mapping issue

Im writing a small program to fetch the categories from the Firestore DB and show in webpage as a list.
My code look like this:
class Category extends Component {
constructor() {
super();
this.state = {'Categories': []}
}
render() {
let categoryList = null;
if (Array.isArray(this.state.Categories)) {
console.log(this.state.Categories);
categoryList = this.state.Categories.map((category) => {
return <li>{category.name}</li>
});
}
return(
<ul>{categoryList}</ul>
);
}
componentWillMount() {
// fetch the data from the Google FireStore for the Category Collection
var CategoryCollection = fire.collection('Category');
let categories = [];
CategoryCollection.get().then((snapshot)=> {
snapshot.forEach ((doc) => {
categories.push(doc.data());
});
}).catch((error) => {
console.log("Error in getting the data")
});
this.setState({'Categories': categories});
}
}
Im able to fetch the data and even populate this.state.Categories, however the map function is not getting executed.
The console.log statement produce an array of values butthe map function in render is not getting executed. Any thoughts?
Console.log output:
You have an error in handling data retrieval. In the last line categories is still empty, so it triggers setState with an empty data set. Should be something lie that
componentWillMount() {
fire.collection('Category').get()
.then(snapshot => {
const categories = snapshot.map(doc => doc.data());
// sorry, but js object should be pascal cased almost always
this.setState({ categories });
})
.catch(error => {
console.log("Error in getting the data")
});
}
Only return the data if the data exists. The simplest way to do this is to replace <ul>{categoryList}</ul> with <ul>{this.state.categories && categoryList}</ul>
I could make it work with a small change (moved this.setState to be inside the callback). Honestly, I still don't understand the difference.
P.S: I come from PHP development and this is my first step into ReactJS.
componentWillMount() {
// fetch the data from the Google FireStore for the Category Collection
var categoryCollection = fire.collection('Category');
let categories = [];
categoryCollection.get().then((snapshot)=> {
snapshot.forEach ((doc) => {
categories.push(doc.data());
});
if (categories.length > 0) {
this.setState({'Categories': categories});
}
}).catch((error) => {
console.log("Error in getting the data");
});
// this.setState({'Categories': categories});
}

Resources