Parse data through API with useEffect for Algolia - reactjs

I need to parse stock data through YahooFinance Stocks API, using RapidAPI here how it would look like as an example response.
https://rapidapi.com/integraatio/api/yahoofinance-stocks1/
The error I am getting is:
Uncaught (in promise) ReferenceError: Cannot access 'data' before
initialization
"results":1294 items
[100 items
0:{4 items
"exchangeCode":"NMS"
"symbol":"1"
"companyName":"1"
"industryOrCategory":"N/A"
}
1:{...}4 items
2:{4 items
"exchangeCode":"NMS"
"symbol":"AAON"
"companyName":"AAON, Inc."
"industryOrCategory":"Industrials"
}
3:{4 items
"exchangeCode":"NMS"
"symbol":"AAPL"
"companyName":"Apple Inc."
"industryOrCategory":"Technology"
}
]
useEffect(() => {
const config = {
headers: {
"x-rapidapi-host": "stock-market-data.p.rapidapi.com",
"x-rapidapi-key": APIKEY,
},
};
const fetchStocks = async () => {
const json = JSON.parse(data);
const results = Object.keys(json["results"]);
const stockInfo = results.map(
(result) =>
(result = {
result,
close: String(json["results"][result]),
})
);
const { data } = await axios.get(
"https://stock-market-data.p.rapidapi.com/market/exchange/nasdaq",
config
);
data.forEach((results) => {
results.objectID = results.length;
});
setStocks(data);
};
fetchStocks();
}, [])

This seems like a marshaling issue in your Javascript more than an Algolia issue. Perhaps because the await axios.get() needs to be in an async function per https://stackabuse.com/making-asynchronous-http-requests-in-javascript-with-axios/
To use the async/await syntax, we need to wrap the axios.get() function call within an async function
Curious the contents of data before and after the data.forEach() (also could that be a map?)

Related

Upload index to Algolia via Yahoo FInance API. Cannot access array even though I can console.log

The problem is that I can console.log the array from the useEffect hook, but when I go to access it, it returns an empty array.
I am trying to upload data to my Algolia index.
Here is the current useEffect:
useEffect(() => {
const fetchListings = () => {
api
.listNasdaq()
.then((response) => {
setListings(response.data);
console.log(response); //I can see the array of data here.
})
.catch((error) => {
console.log(error);
});
};
fetchListings();
}, []);
api.js:
listNasdaq: () =>
exchangeApi({
method: "GET",
url: "/companies/list-by-exchange",
transformResponse: [
function (data) {
// Do whatever you want to transform the data
console.log("Transforming Nasdaq Data...");
const json = JSON.parse(data);
const stocks = Object.keys(json["results"]);
const stockNames = stocks.map(
(stock) =>
(stock = {
stock,
stockName: String(json["results"][stock]["companyName"]),
symbol: String(json["results"][stock]["symbol"]),
industry: String(json["results"][stock]["industryOrCategory"]),
})
);
data = {
stockNames,
};
return data;
},
],
}),
Algolia:
nasdaqIndex
.saveObjects(listings, {
autoGenerateObjectIDIfNotExist: true,
})
.then(({ objectIDs }) => {
console.log("algolia stuff", objectIDs);
});
I'm a little confused by your map function. Are you injecting the full stock object back into itself ((stock = { stock, ...)? What does the final stock object look like when you log it? I'm worried that might be confusing Algolia when you go to save the record.
const stockNames = stocks.map(
(stock) =>
(stock = {
stock,
stockName: String(json["results"][stock]["companyName"]),
symbol: String(json["results"][stock]["symbol"]),
industry: String(json["results"][stock]["industryOrCategory"]),
})
);
Also, I assume the call to nasdaqIndex.saveObjects() occurs in setListings()? It looks like some of this code may be missing here.

mocking my fetch function does not work, keeps getting back undefined

I am trying to mock a simple function that uses fetch. The function in question looks like this:
export const getPokemon = async () => {
//function that makes the API call and fetches our pokemon
//getPokemon.js
const randomId = () => Math.floor(Math.random() * 151 + 1);
const pokemonApiUrl = `https://pokeapi.co/api/v2/pokemon/`;
export const getPokemon = async () => {
//function that makes the API call and fetches our pokemon
const id = randomId();
let pokemon = { name: "", image: "" };
try {
const result = await fetch(`https://pokeapi.co/api/v2/pokemon/${id}`);
console.log(result)
const data = await result.json();
pokemon.name = data.name;
pokemon.image = data.sprites.other["official-artwork"].front_default;
return pokemon;
} catch (err) {
console.error(err);
Whenever I try to mock the function in my unit tests I receive back a TypeError: Cannot read property 'json' of undefined. Basically, the result comes back as undefined and thus we cannot call our .json(). It works fine in production and the fetch calls work as expected. I am using React Testing Library and Jest.
I have tried to replaced the global fetch in the following manner:
//PokemonPage.test.js
global.fetch = jest.fn(() =>
Promise.resolve({
json: () => Promise.resolve({ data: { name: 'Charizard' } }),
})
);
I've also tried to create a fakeFetch and send it in to my function as a dependency injection, but I get the exact same error.
Lastly, I've tried to install jest-fetch-mock but yet again I am getting the same error... Has anyone encountered the same thing?
The failing function gets called in production here:
function Pokemon({ pokemonTrainer }) {
...
useEffect(() => {
async function fetchData() {
pokemonRef.current = await getPokemon();
setPokemonList((prev) => [
...prev,
{ name: pokemonRef.current.name, image: pokemonRef.current.image },
]);
}
fetchData();
}, []);
...
}

Axios Error Networ error on request Google place api

im trying to make a request to google api but returns me network error. If i put the url in the browser, brings me the information correctly.I tryed to formate the request without success. The google places search works correctly too.
export const fetch_information = (skip, limit, filter) => async (dispatch) => {
try {
var url = `https://maps.googleapis.com/maps/api/place/details/json?place_id=ChIJk0aJYPbk3JQRLpKN20Jecko&fields=name,rating,formatted_phone_number&key=MyKey`;
const {data} = await axios.get(url)
console.log(data)
} catch (error) {
console.log(error.message)
}
}
and
export const fetch_information = (skip, limit, filter) => async (dispatch) => {
try {
var url = `https://maps.googleapis.com/maps/api/place/details/json?`;
let config = {
params: {
place_id: 'ChIJk0aJYPbk3JQRLpKN20Jecko',
key: 'myKey',
},
}
const {data} = await axios.get(url, config)
console.log(data)
} catch (error) {
console.log(error.message)
}
}
I think that the request looks a bit messy. I'm under the impression that you are trying to pass results to a redux store. Let's see if we can clean this up a bit.
export const fetch_information = async () => dispatch => {
const req = await axios.get("https://maps.googleapis.com/maps/api/place/details/json?place_id=ChIJk0aJYPbk3JQRLpKN20Jecko&fields=name,rating,formatted_phone_number&key=MyKey");
const data = await req.json();
return data;
//or, for your purpose...
console.log(data);
//can also dispatch for store
}
I didn't see anything you were passing as necessary for this.

Send array from React to Express/Node to query Mongo

I am having difficulty sending an array of Id numbers from React state, through Node/Express, then eventually to MongoDB.
The main difficulty is how to send an array from React to the server. Once I have it there in a usable array form, I believe I know how to query MongoDB using an array.
I have been trying to do this mainly with a GET method and have been unsuccessful using req.params or req.query. I have tried this with several versions of string templates, and using what the Axios docs say as well as many other answers on stack overflow, none have been successful.
I have also tried a couple of versions of a PUT request and also with no success.
The array of Ids already exists in props.completedJobs:
In React:
useEffect(() => {
const fetchData = async () => {
let completedJobsArray = props.completedJobs;
let json = JSON.stringify(data);
let getData = {jsonData: json};
const result = await axios('/api/brief/brief-array/' + getData);
setData(result.data);
};
fetchData();
}, []);
In Express app:
app.use("/brief", briefRouter);
then in the router:
router.get("/brief-array/:briefArray", briefController.brief_findArrayById);
then the function:
exports.brief_findArrayById = async (req, res) => {
try {
// console.log("req.body: ", req.body);
// console.log("req: ", req);
// console.log("req.query: ", req.query);
// console.log("req.params: ", JSON.stringify(req.params.briefArray));
const briefs = await GWJob.find({"_id": {$in: ["5d1297512c68bc49060bce7b", "5d1297092c68bc49060bce7a"] } });
res.json(briefs);
} catch (err) {
res.json({ message: err });
}
}
The MongoDB query works with the hard-coded IDs, but cannot get any of the above versions of console.logs to display any value other than undefined or "object object".
I am also unable to query the database using an array through Postman.
I expect to send 1 or more id numbers in an array to MongoDB, and receive those documents back to React on the front end. Any help with sending an array from state in React through Node/Express is much appreciated! Thank you.
You are sending Long string through the URL which is a limited length (~2047 char),
the safe away to accomplish what you are trying to do to use a post or put method and send the list in the body.
Example:
useEffect(() => {
const fetchData = async () => {
let completedJobsArray = props.completedJobs;
const result = await axios({
method: 'post',
url: '/brief-array',
data: completedJobsArray
});
setData(result.data);
};
fetchData();
}, []);
Another attempt, still returning undefined. If anyone has links to a thorough resource on sending/receiving data I would much appreciate it. I always have spent days trying to get one of these to work, until I started using Axios, but if I need to go beyond what I can do with Axios I am back to square one. Many thanks.
useEffect(() => {
const fetchData = async () => {
let completedJobsArray = props.completedJobs;
let queryData = {completedJobsArray};
const settings = {
method: 'POST',
headers: { 'Content-Type': 'application/json; charset=utf-8'},
body: JSON.stringify(queryData)
};
try {
const fetchResponse = await fetch(`/api/brief/brief-array`, settings);
const returnedData = await fetchResponse.json();
setData(returnedData);
} catch (error) {
console.error("error: ", error);
}
}
fetchData();
}, []);

How to chain 2 API calls with redux thunk?

I'm making a weather app, which detects your current location's coordinates by making an API call to freegeoip.com, then takes those coordinates to make an API call to openweathermap.org to fetch your current location's weather.
How would I do this with redux thunk?
This is my current action creator code:
import axios from 'axios';
export const FETCH_CURRENT_CITY = 'FETCH_CURRENT_CITY';
const API_KEY = '95108d63b7f0cf597d80c6d17c8010e0';
const ROOT_URL = `http://api.openweathermap.org/data/2.5/weather?appid=${API_KEY}`;
export function fetchCurrentCityCoords() {
const request = axios.get('http://freegeoip.net/json/');
console.log('Request coords:', request);
return (dispatch) => {
request.then(({response}) => {
dispatch(fetchCurrentCityWeather(response));
});
};
}
export function fetchCurrentCityWeather(coords) {
const lat = coords.data.latitude;
const lon = coords.data.longitude;
const url = `${ROOT_URL}&lat=${lat}&lon=${lon}`;
const request = axios.get(url);
console.log('Request weather:', request);
return (dispatch) => {
request.then(({response}) => {
dispatch({
type: FETCH_CURRENT_CITY,
payload: response
})
});
};
}
Console logs:
Request coords: Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}
Uncaught (in promise) TypeError: Cannot read property 'latitude' of undefined
at fetchCurrentCityWeather (bundle.js:26131)
at bundle.js:26125
Are you sure the API response holds a data property?
try debugging the first line of fetchCurrentCityWeather function and check what coords holds, or just try console.log(coords); to see it's object structure.
maybe this:
const lat = coords.data.latitude;
const lon = coords.data.longitude;
should be like that:
const lat = coords.latitude;
const lon = coords.longitude;
Edit
following your comment,
for debug purpose try editing your fetchCurrentCityWeather function to this code and see what is printed to the console:
export function fetchCurrentCityWeather(coords) {
console.log(coords);
//const lat = coords.data.latitude;
//const lon = coords.data.longitude;
//const url = `${ROOT_URL}&lat=${lat}&lon=${lon}`;
//const request = axios.get(url);
//console.log('Request weather:', request);
//return (dispatch) => {
//request.then(({response}) => {
// dispatch({
//type: FETCH_CURRENT_CITY,
// payload: response
//})
//});
// };
}
EDIT #2
following your comment, you are getting undefined hence you can't use .map on it. this is your answer to the error.
As for why you are getting undefined, i think it's because this block of code:
return (dispatch) => {
request.then(({response}) => {
dispatch(fetchCurrentCityWeather(response));
});
};
You are doing "Destructuring" to the response parameter with this {response}.
try this instead:
return (dispatch) => {
request.then((response) => {
dispatch(fetchCurrentCityWeather(response));
});
};
Uncaught (in promise) TypeError: Cannot read property 'latitude' of undefined
at fetchCurrentCityWeather (bundle.js:26131)
at bundle.js:26125
Problems appears to be your const lat = coords.data.latitude it's undefined.
So you have to check if the
return (dispatch) => {
request.then(({response}) => {
dispatch(fetchCurrentCityWeather(response));
});
CallsfetchCurrentCityWeather with correct response object you expect to have properties data.latitude & data.longitude you seem to incorrectly refer.
Advise.
console.log(coords); inside fetchCurrentCityWeather function to see if it has those properties.

Resources