How to make a JSON response data global :) - javascript

Currently working on a stock project for my portfolio and I am using finnhub as the API.
I can log everything to my console. However I cannot render it as the "data" is not globally declared and must be inside of a certain function.
I tried rendering globally but had no luck...
So my question is how do I make 'data' global so that I can render it inside of the "StockHeader's" return ?
Heres what I have so far...
import React,{ useState, useEffect } from 'react';
const StockHeader = (data) => {
const [stocks, setStocks] = useState({});
const getStocks = () => {
//setting stocks
setStocks(stocks)
}
//calling it once
useEffect(()=> {
getStocks();
}, [])
//using finhubs ready made code from documentation
const finnhub = require('finnhub');
const api_key = finnhub.ApiClient.instance.authentications['api_key'];
api_key.apiKey = "my apikey"
const finnhubClient = new finnhub.DefaultApi()
finnhubClient.quote("AAPL", (error, data, response) => {
//I can log the data but I cant show it in my component
console.log(data.c)
});
return (
<>
{/* This says that data is not defined */}
<h1>{data.c}</h1>
</>
)
}
export default StockHeader

You just need a little bit of code reorganization so that the API request only happens once and so that you can use setStocks to store it:
const StockHeader = (data) => {
const [stocks, setStocks] = useState({});
useEffect(()=> {
//this could be separated into a `getStocks` function if you want
const finnhub = require('finnhub');
const api_key = finnhub.ApiClient.instance.authentications['api_key'];
api_key.apiKey = "my apikey"
const finnhubClient = new finnhub.DefaultApi()
finnhubClient.quote("AAPL", (error, data, response) => {
console.log(data.c);
setStocks(data.c);
});
}, []);
return (
<>
{/* You probably don't want to render `stocks` itself, but this shows you how to get access to the variable */}
<h1>{stocks}</h1>
</>
)
}

Related

Why does my component fail to construct Url?

I'm fairly new to React development and hope someone can help me with this problem. I'm coding along with a YouTube video https://www.youtube.com/watch?v=XtMThy8QKqU&t=10138s (2:55:00 shows what it is supposed to do)and for some reason I can't find the mistake I'm making. When I test my app on localhost the window in which the trailer is supposed to play is only displayed when I click certain movie covers but not when I click on others. my other problem is that it will never actually play a trailer. The console displays the error you can hopefully see here [1]: https://i.stack.imgur.com/vC6Sh.jpg
import movieTrailer from "movie-trailer";
import React, { useEffect, useState } from "react";
import YouTube from "react-youtube";
import axios from "./axios";
import "./Row.css"
const base_url = "https://image.tmdb.org/t/p/original/";
function Row({ title, fetchUrl, isLargeRow }) {
const [movies, setMovies] = useState([]);
const [trailerUrl, setTrailerUrl] = useState("");
//A snippet of code which runs based on a specific condition or variable
useEffect(() => {
// if brackets are blank [] it means run once when row loads, and don't run again
async function fetchData() {
const request = await axios.get(fetchUrl);
// console.log(request.data.results);
setMovies(request.data.results)
return request;
// async function fetchData() {
// try{
// const request = await axios.get(fetchUrl);
// console.log(request);
// return request;
// }
// catch (error){
// console.log(error);
// }
}
fetchData();
}, [fetchUrl]);
const opts = {
height: '390',
width: '100%',
playerVars: {
// https://developers.google.com/youtube/player_parameters
autoplay: 1,
},
};
//console.log(movies);
const handleClick = (movie) => {
if (trailerUrl){
setTrailerUrl('');
} else {
movieTrailer(movie?.name || "")
.then ((url) => {
const urlParams = new URLSearchParams(new URL(url).search);
setTrailerUrl(urlParams.get("v"));
}).catch(error => console.log(error));
}
};
return(
<div className="row">
<h2>{title}</h2>
<div className="row__posters">
{movies.map(movie => (
<img
key={movie.id}
onClick={() => handleClick(movie)}
className= {`row__poster ${isLargeRow && "row__posterLarge"}`}
src={`${base_url}${isLargeRow ? movie.poster_path : movie.backdrop_path}`} alt={movie.name}/>
))}
</div>
{trailerUrl && <YouTube videoId="{trailerUrl}" opts={opts} /> }
</div>
)
}
export default Row
Invalid property name in movie
Taking a look at the tmdb docs it will show you what the properties of each object has. In this case, there is no name. Try using something like movie.title
In your handleClick() function you could use movie?.title.
Trying to use movie.name will give back a null value. Which errors out movieTrailer() and you get no YouTube url back.
Create handle function like this and the call it in your return function and use however you want... mainly should be used by using onClick method

i'm trying to make a axiosGET request to my react component, i get the object on the console.log. But when i try to render it i get a "is not defined"

//component
const Clientslist = () => {
const classes = useStyles()
axios.get('/api/clients').then(resp => {
const {clients} = resp.data
console.log(clients) // i get the data on the terminal
})
return(
...
{
clients.map(client => ( //clients is not defined
<Grid key={client._id} item xs={12} sm={6} md={4}>
<Card
clientName={client.clientName}
...
)
}
//controller
const get = async (req, res) => {
await dbConnect()
const clients = await ClientsModel.find()
res.status(200).json({ success: true, clients})
}
I thing my request code is poor, if someone helps me fix the problem and even a code refactor for a better and clean code. It would be great. Thanks.
your clients variable is defined inside the scope inside the axios callback, and can't be accessed from outside, but if you modified it alittle bit, you can save it inside a local state variable, like: (3 new lines are marked with //***)
//component
const Clientslist = () => {
const classes = useStyles()
//*** Adding clients var with initial value as empty array
const [clients, setClients] = useState([]) //***
axios.get('/api/clients').then(resp => {
const {clients} = resp.data
console.log(clients) // i get the data on the terminal
setClients(clients) //*** this would save the new clients in the sate
})
In your code, clients variable is in the local scope of axios thus not accessible in the return statement.
As you are using React functional Component, we can use useState hook which helps us to track the state of the variable
//component
import React, { useState } from 'react';
const Clientslist = () => {
const classes = useStyles();
const [clients, setClients] = useState([]);// empty array denotes initial state
axios.get('/api/clients').then(resp => {
const {clients} = resp.data
console.log(clients)
setClients(clients); // sets the state of variable clients to the received data
})
return(
...
{
clients.map(client => (// updated clients can be used here to display .Also check for the valid response before mapping
<Grid key={client._id} item xs={12} sm={6} md={4}>
<Card
clientName={client.clientName}
...
)
}
Helpful resources :
https://reactjs.org/docs/hooks-state.html
https://www.geeksforgeeks.org/what-is-usestate-in-react/

Data from review steamapi is not being displayed. ReactJS

I am making an api call to the steam review api with this link: "api link"
I have used another link with my code and was able to get responses and even display the data on my screen, so I have no faulty code. I am currently using this to try and get the result content: comment.reviews.review
This is my complete code:
function Home() {
const [comments, setComments] = useState([]);
useEffect(() => {
fetchComments();
}, []);
useEffect(() => {
console.log(comments);
}, [comments]);
const fetchComments = async () => {
const response = await axios(
"https://store.steampowered.com/appreviews/1389990?json=1&language=english"
);
setComments(response.data);
};
var limitComments = comments.slice(0, 3);
return (
{limitComments &&
limitComments.map((comment) => (
<p>{comment.reviews.review}</p>
))}
);
}
export default Home;
What is wrong with request? I have tried using different keys like comment.author.reviews.review.

React.js display image from saved api response

So I want to do a simple image fetch from API. My goal is to display random image from API. Now it says "Data" is not defined. I have no idea why it does that because my console.logs were working before trying to show it on page.
This is my App.js
import React,{useEffect, useState} from 'react';
import Dog from './doggo';
//Main component
function App() {
const [dogs, setDog] = useState();
useEffect(() => {
getDog();
}, []);
//Function to get data
const getDog = async () => {
//Fetch from url
const response = await fetch("https://dog.ceo/api/breeds/image/random");
//Store answer in data
const data = await response.json();
//Place data.message in setDog
setDog(data.message);
console.log(data.status);
//data.message contains image url
console.log(data.message);
};
return(
<div>
<h1>Press button to see your future dog!</h1>
<button type="submit">See your dog!</button>
<Dog
image={data.message}
/>
</div>
);
};
export default App;
I reformatted you code a bit to take care of some issues.
As other commenters have stated, data is out of scope where you're trying to access it. (It's only available inside of the getDog() function.)
export default function App() {
const [dog, setDog] = useState();
const getDog = async () => {
const response = await fetch("https://dog.ceo/api/breeds/image/random");
const data = await response.json();
setDog(data.message);
};
return (
<div>
<h1>Press button to see your future dog!</h1>
<button
onClick={() => {
getDog();
}}
>
See your dog!
</button>
{dog ? <Dog image={dog} /> : null}
</div>
);
}
Working Codepen
use {dogs} instead of {data.message} in <Dog image={data.message}/> data is a variable only for the getDog() function.

Fetching data from Prismic API using React Hooks

I'm trying to query data from the Prismic headless CMS API and running into problems using React Hooks. The prismic API is returning null, though I know its being passed down correctly as I can query it successfully without using react hooks.
Heres my current compontent code. Its returning "cannot read property 'api' of null". It doesn't reach the 'data' console log.
const Footer = ({ prismicCtx }) => {
const [links, setLinks] = useState([]);
useEffect(() => {
const fetchLinks = async () => {
const data = await prismicCtx.api.query([
Prismic.Predicates.at('document.tags', [`${config.source}`]),
Prismic.Predicates.at('document.type', 'footer'),
]);
console.log('data:', data);
setLinks(data.results[0].data);
};
fetchLinks();
}, []);
return (
<div>
<h1> Footer </h1>
</div>
);
};
export default Footer;
It seems to be a case where on initial render prismicCtx is null and only on the subsequent render you receive the updated value. The solution is obviously to call the effect on change of prismicCtx, but you if you just want to call the api on initial render you would need to keep track of whether you called the api earlier or not which you can achieve by using useRef and also you don't need to set the state as empty if prismicCtx doesn't exist
const Footer = ({ prismicCtx }) => {
const [links, setLinks] = useState([]);
const isFirstCall = useRef(true);
useEffect(() => {
if(prismicCtx && isFirstCall.current) {
const fetchLinks = async () => {
const data = await prismicCtx.api.query([
Prismic.Predicates.at('document.tags', [`${config.source}`]),
Prismic.Predicates.at('document.type', 'footer'),
]);
console.log('data:', data);
setLinks(data.results[0].data);
};
fetchLinks();
isFirstCall.current = false;
}
},[prismicCtx]);
return (
<div>
<h1> Footer </h1>
</div>
);
};
export default Footer;
Figured it out, I beleive. PrismicCTX was being changed up the tree so it was switching to undefinded. A simple if/else fixed it and making it so it only updated on that prop change. Still not sure if best practice though!
const Footer = ({ prismicCtx }) => {
const [links, setLinks] = useState([]);
useEffect(
() => {
const fetchLinks = async () => {
const data = await prismicCtx.api.query([
Prismic.Predicates.at('document.tags', [`${config.source}`]),
Prismic.Predicates.at('document.type', 'footer'),
]);
console.log('data:', data);
setLinks(data.results[0].data);
};
if (prismicCtx) {
fetchLinks();
} else {
setLinks([]);
}
},
[prismicCtx]
);
return (
<div>
<h1> Footer </h1>
</div>
);
};
export default Footer;

Categories