i was trying to fetch a data for a project but everytime i'm converting the fetch data to json it returns me
SyntaxError: Unexpected token < in JSON at position 0
i don't understand why it's showing me this
import React,{useContext,useState,useEffect} from 'react'
const url = 'www.thecocktaildb.com/api/json/v1/1/search.php?s='
export default function AppProvider({children}) {
const [loading,setLoading] = useState(true)
const [searchTerm,setSearchTerm] = useState('a')
//set it as 'a' for suggestion at search bar at beginning.
const [cocktails,setCocktails] = useState([])
const fetchUrl = async ()=>{
setLoading(true)
try {
const response = await fetch(`${url}${searchTerm}`)
//(${url}${searchterm} helps me to fetch data at first with names that starts with 'a' for suggestion///
const data = await response.json()
setLoading(false)
} catch (error) {
console.log(error)
}
}
useEffect(()=>{
fetchUrl()
},[searchTerm])
please visit the API page from the URL & see if there's an issue with the data. the data is not fetching. what's the issue?
Link
Doing
fetch('www.thecocktaildb.com/')
will fetch not that website, but that path relative to the current path. For example, doing so here on Stack Overflow results in the URL being fetched being
https://stackoverflow.com/questions/72914244/www.thecocktaildb.com/
which, of course, doesn't exist - and presumably that URL doesn't exist on your site either.
Use the full path.
const url = 'https://www.thecocktaildb.com/api/json/v1/1/search.php?s='
I'd also recommend only calling the API when searchTerm isn't empty, and perhaps add a debounce of a few hundred milliseconds so as not to call it too often and to keep the client from being blocked.
Related
I'm relatively new working with promises in JS. I got the API call to work on the initial homepage, but I'm having issues when I go to another page that is using the same API call.
In my api.js file I have the following:
const key = apiKey;
const commentsUrl = axios.get(`https://project-1-api.herokuapp.com/comments/?api_key=${key}`);
const showsUrl = axios.get(`https://project-1-api.herokuapp.com/showdates?api_key=${key}`);
async function getData() {
const allApis = [commentsUrl, showsUrl];
try {
const allData = await Promise.allSettled(allApis);
return allData;
} catch (error) {
console.error(error);
}
}
In my index.html
import { getData } from "./api.js";
let data = await getData(); //This works and gathers the data from the API.
In my shows.html
import { getData } from "./api.js";
let showsData = await getData(); //This does not and says that cannot access commentsUrl (api.js) before it is initialized. But it is?
If I comment out the code from "show", the API GET request works fine and the index page loads the API data correctly. Can anyone explain to me what's happening and why I would be getting the uninitialized error?
I also should note that if I split the API calls onto two seperate two js files (one for the index, one for the shows), the API calls works and displays the data as it is intended to.
On the homepage, the code is executing the 2 GET requests on page load/initialization of the JS code. When you navigate away from the homepage, presumably with some sort of client-side routing, the 2 GET requests no longer reference 2 Promises as they have already been executed.
You could instead move the GET requests into your function like:
const key = apiKey;
async function getData() {
try {
const commentsUrl = axios.get(`https://project-1- api.herokuapp.com/comments/?api_key=${key}`);
const showsUrl = axios.get(`https://project-1-api.herokuapp.com/showdates?api_key=${key}`);
const allApis = [commentsUrl, showsUrl];
const allData = await Promise.allSettled(allApis);
return allData;
} catch (error) {
console.error(error);
}
}
When request is sent, response is always the same on page reload in Chrome but random (as it should be) in FireFox. On button click data is always the same after page reload.
I want to make a request on each button click to store different data in the state hook.
I also tried it in vanilla js and response is the same as well.
What is causing data to always be the same and not random on request?
I will store previously fetched data in the state but first have to figure out why is it always the same, I would appreciate any help as I'm new to these api calls and react as well.
App.js:
import FetchColor from './common/FetchColor';
import ColorList from './components/ColorList';
import { useEffect, useState } from 'react';
function App() {
const [colorData, changeColor] = useState('');
const changeColorHandler = () => {
FetchColor(changeColor);
};
useEffect(() => {
FetchColor(changeColor);
}, []);
return (
<div className='App'>
<button onClick={changeColorHandler}>
{colorData ? colorData.tags[0].name : 'Change Color'}
</button>
<ColorList color={colorData} />
</div>
);
}
export default App;
FetchColor.js:
const FetchColor = async (changeColor) => {
const response = await fetch('https://www.colr.org/json/color/random');
const data = await response.json();
const [color] = data.colors;
changeColor(color);
};
export default FetchColor;
Vanilla JavaScript script.js:
const fetchButton = document.getElementById('fetch-api');
fetchButton.addEventListener('click', fetchColorFunc);
async function fetchColorFunc() {
const response = await fetch('https://www.colr.org/json/color/random');
console.log(`Response: ${response}`);
const data = await response.json();
console.log(`Data: ${data}`);
}
This is most likely due to caching. If you look at the requests in Chrome's Network panel of the Developer Tools, you should see that the requests are cached and therefore always return the same value.
Fetch optionally takes an init object containing custom settings that will be applied to the request, including cache. For example, you can pass cache: "no-cache" or cache: "no-store" to bypass caching (see documentation for details and differences) and you will get random results with each request.
See the following snippet as an example:
async function fetchColorFunc() {
const response = await fetch('https://www.colr.org/json/color/random', { cache: "no-cache" });
const data = await response.json();
console.log(`Data: ${JSON.stringify(data)}`);
}
fetchColorFunc();
Chrome caches the request. You can see this, if you open the developer tools and check on the network tab. You will see, that all later calls are fetched from disk cache.
You can either add some random query to the url
const response = await fetch('https://www.colr.org/json/color/random?t='+Date.now());
or you can add a cache-control header with value no-cache.
const response = await fetch('https://www.colr.org/json/color/random', { headers : {"cache-control": "no-cache"}});
But that will trigger a preflight request and requires the server to allow CORS from your origin.
I'm making a react app that works with a API that provides data to my App. In my data base I have data about pins on a map. I want to show the info of those pins on my react app, I want them to render. I get that information with axios and this url: http://warm-hamlet-63390.herokuapp.com/pin/list
I want to retrieve the info from that url, with axios.get(url), stringify the JSON data and then parse it to an array of pins.
The Problem:
My page will be rendered before I get the data back from the server, because axios is async, so I will not be able to show anything. UseEffect and useState won't work because I need something in the first place (I think).
What i've tried:
I tried to use useEffect and useState, but as I said, I think I need something in the first place to change it after. I also tried to use await, but await won't stop the whole React App until it has a response, although it would be nice if there is something that stops the app and waits until I have the array with the info so I can show it on the App then. I tried everything with async. I'm fairly new to React so there might be something basic i'm mssing (?). I've been on this for days, I can't get this to work by any means.. Any help, youtube videos, documentation, examples, is help. Anything. How the hell do I render something that needs to wait for the server respond?
My code:
//function that stores the data in the result array,
//but result array will only be available after the
//server response, and after the page is rendered
async function pin(){
const result = []
var url = "http://warm-hamlet-63390.herokuapp.com/pin/list"
const res = await axios.get(url)
console.log(res.data.data);
if(res.data){
const txt = JSON.stringify(res.data.data)
const result = JSON.parse(txt)
console.log(result);
}
return result;
}
class App extends React.Component{
render(){
return(
<div>
<Pin/>
<Mapa/>
</div>
)
}
}
export default App
I don't fully understand what you are trying to output but how you would usually handle this is with both the useState hook and the useEffect hook see example below.
//function that stores the data in the result array,
//but result array will only be available after the
//server response, and after the page is rendered
const pin = () => {
const [result, setResults] = useState([]);
var url = "http://warm-hamlet-63390.herokuapp.com/pin/list"
useEffect(() => {
//Attempt to retreive data
try {
const res = transformData();
if (res) {
// Add any data transformation
setResults(transformData(res))
}
else {
throw (error)
}
}
catch (error) {
//Handle error
}
}, [])
// Handle data transformation
const transformData = async () => {
const res = await axios.get(url)
const txt = JSON.stringify(res.data.data)
const result = JSON.parse(txt)
return result
}
if (!result) {
// Return something until the data is loaded (usually a loader)
return null
}
// Return whatever you would like to return after response succeeded
return <></>;
}
This is all assuming that Pin is a component like you have shown in your code, alternatively, the call can be moved up to the parent component and you can add an inline check like below to render the pin and pass some data to it.
{result && <Pin property={someData} />}
Just a bit of background the useEffect hook has an empty dependency array shown at the end "[]" this means it will only run once, then once the data has updated the state this will cause a rerender and the change should be visible in your component
Rest assured, useEffect() will work. You need to use a condition to conditionally render the content when it comes back from the server.
In the example below if results has a length < 1 the message Loading ... will be rendered in the containing <div>, once you're results are received the state will be updated (triggering a re-render) and the condition in the template will be evaluated again. This time though results will have a length > 1 so results will be rendered instead of Loading ...
I’m operating under the assumption that you’re function pin() is returning the results array.
const app = (props) => {
const [results, setResult] = useState([]);
React.useEffect(() => {
const getPin = async () => {
if (!results) {
const results = await pin();
setResult([…results])
}
}
getPin();
},[results]);
return (
<div>
{result.length ? result : 'Loading ... '}
</div>
)
}
https://ibb.co/dsNrnPQ -- screenshot of error
I get a problem with an async event.
When logging into the site, when locale-storage is not ready yet. I can't get it async.
After refreshing the page, the problem goes away.
Unhandled Rejection (SyntaxError): Unexpected token u in JSON at position 0
Problem in string
const userData = await userDataGetter();
export function setBalanseFetch(){
return async dispatch => {
const userData = await userDataGetter();
const userID = await userData.userId;
try{
const respone = await axios.post('/api/profile', {userID})
const json = await respone["data"];
const FetchBalanse = json.items[0].balanse;
dispatch( {type: FETCH_BALANSE, payload: Number(FetchBalanse)})
}catch(e){
console.log(`Axios spend balanse request failed: ${e}`);
}
}
}
code function userDataGetter
async function userDataGetter(){
const userData = await JSON.parse(localStorage.userData);
return userData;
}
export default userDataGetter
You have:
const userData = await JSON.parse(localStorage.userData);
However, JSON.parse is not an asynchronous function. It does not wait for a localStorage key to be present and ready, which is what your code seems to want it to do. (Also, as a comment pointed out, you want localStorage.get('userData')). Nor are you checking that it is present at all.
You also don't show where the localStorage is getting set. But likely your solution will be to then trigger the code that depends on it after you know its been set from the same place that's setting it, and when you need to access it any other time, check for its presence first.
When trying to use axis to query an external Weather API, I get this error
ReferenceError: axios is not defined
at getTropicalCyclones (vm.js:16:9)
Here is my action for getTropicalCyclones {}
(of course I have to hide my client ID and secret)
const getTropicalCyclones = async () => {
const BASE_WEATHER_API = `https://api.aerisapi.com/tropicalcyclones/`
const CLIENT_ID_SECRET = `SECRET`
const BASIN = `currentbasin=wp`
const PLACE = `p=25,115,5,135` // rough coords for PH area of responsibility
const ACTION = `within` // within, closest, search, affects or ''
try {
let text = ''
let response = {}
await axios.get(
`${BASE_WEATHER_API}${ACTION}?${CLIENT_ID_SECRET}&${BASIN}&${PLACE}`
)
.then((resp) => {]
response = resp
text = 'Success retrieving weather!'
})
.catch((error) => {
console.log('!! error', error)
})
const payload = await bp.cms.renderElement(
'builtin_text',
{
text,
},
event.channel
)
await bp.events.replyToEvent(event, payload)
} catch (e) {
// Failed to fetch, this is where ReferenceError: axios is not defined comes from
console.log('!! Error while trying to fetch weather info', e)
const payload = await bp.cms.renderElement(
'builtin_text',
{
text: 'Error while trying to fetch weather info.',
},
event.channel
)
await bp.events.replyToEvent(event, payload)
}
}
return getTropicalCyclones()
So my question is, how do I import axios? I've tried
const axios = require('axios')
or
import axios from 'axios';
but this causes a different error:
Error processing "getTropicalCyclones {}"
Err: An error occurred while executing the action "getTropicalCyclones"
Looking at the package.json on GitHub, it looks like axios is already installed
https://github.com/botpress/botpress/blob/master/package.json
However, I cannot locate this package.json on my bot directory...
Secondly, based on an old version doc it looks like this example code just used axios straight
https://botpress.io/docs/10.31/recipes/apis/
How do I use axios on Botpress?
Any leads would be appreciated
Botpress: v11.0.0
Simply use ES6 import.
include this line at the top of your code.
import axios from 'axios';
Note: I'm expecting that the axios is already installed