Returning data from getStaticProps - javascript

I'm trying to create a function that fetches data from The Guardian API but seem to be getting an error. The response returns this information:
And here is the code for the asynchronous function:
export async function getStaticProps() {
try {
const res = await fetch(
"https://content.guardianapis.com/search?api-key=xxxxxxxx&show-fields=thumbnail"
);
const { results } = await res.json();
const newsList = results.map((news) => {
return { ...news };
});
return {
props: { newsList },
};
} catch (err) {
console.error(err);
}
}

You almost got it. Only 1 thing you are missing is to return props even in the catch block
export async function getStaticProps() {
try {
const res = await fetch(
"https://content.guardianapis.com/search?api-key=xxxxxxxx&show-fields=thumbnail"
);
const { results } = await res.json();
const newsList = results.map((news) => {
return { ...news };
});
return {
props: { newsList },
};
} catch (err) {
console.error(err);
return {
notFound: true /// for rendering 404 page
};
}
}

Related

Async function inside of the React Component returns 'PromiseĀ {<pending>}' no matter what I do

So, I'm trying to run a asynchronous function inside of the functional component in React (NextJS). But no matter what I do, the function just returns a pending promise like this: PromiseĀ {<pending>}. I tried fetching the data from a dummy API, and it works as its supposed to.
The thing is that for this particular case, I need to grab the access_token from the getServerSideProps, which is probably the reason why I am facing these problems (I might be wrong though).
It's worth noting that using a console.log inside of the function, instead of the standard return, gives the correct result.
const checkLoved = async (id: string) => {
try {
const response = await fetch(`https://api.spotify.com/v1/me/tracks/contains/?ids=${id}`, {
headers: {
Authorization: `Bearer ${test.access_token}`,
},
});
const data = await response.json();
return data[0];
} catch (error) {
console.error(error);
}
};
export async function getServerSideProps(context) {
const session = await getSession(context);
if (!session) {
return {
redirect: {
destination: '/login',
permanent: false,
},
};
}
const {
token: { accessToken },
} = session;
const test = await getAccessToken(accessToken);
return {
props: { test, accessToken },
};
}
Additonal info
What I'm trying to achieve:
const Discover: NextPageWithLayout = ({ test }: IDiscover) => {
const checkLoved = async (id: string) => {
try {
const response = await fetch(`https://api.spotify.com/v1/me/tracks/contains/?ids=${id}`, {
headers: {
Authorization: `Bearer ${test.access_token}`,
},
});
const data = await response.json();
return data[0];
} catch (error) {
console.error(error);
}
};
const array = [{ test: 1 }, { test: 2 }];
return (
<div>
{array.map((item) => {
console.log();
return <Component test={checkLoved('7jCy1opEtV4a0TnKrtsSdo')}>{item.test}</Component>;
})}
</div>
);
};
Fixed it by creating a custom hook.
const useLoved = (id, access_token) => {
const [loved, setLoved] = useState(null);
useEffect(() => {
const isLoved = async () => {
const response = await fetch(`https://api.spotify.com/v1/me/tracks/contains/?ids=${id}`, {
headers: {
Authorization: `Bearer ${access_token}`,
},
});
const data = await response.json();
setLoved(data[0]);
};
isLoved();
});
return loved;
};
Then you just need to call it:
const loved = useLoved('7jCy1opEtV4a0TnKrtsSdo', test.access_token);

Getting the API by the callback function in React

I have a function, that connects to the API and returns the data:
import {API_KEY, API_URL} from "./constants";
// /**
// * Fetch all tasks
// * #param {function} successCallback - Function that saves incoming data
// */
export const getOperations = async (id, successCallback) => {
try {
const response = await fetch(`${API_URL}/tasks/${id}/operations`, {
headers: {
Authorization: API_KEY,
},
});
const data = await response.json();
if (data.error) {
throw new Error('Error!');
}
successCallback(data.data);
} catch (err) {
console.log(err);
}
};
Then, in one of my react component i call that function to get a data from the specified API:
The props is a required ID.
const [operations, setOperations] = useState([])
console.log(props)
useEffect(() => {
try {
getOperations(data => (props, setOperations(data)))
} catch(e) {
console.log(e)
}
}, [])
The problem is, that my API looks like:
`...api/tasks/function%20(data)%20%7B%20%20%20%20%20%20%20%20return%20props,%20setOperations(data);%20%20%20%`20%20%20%7D/operations`
So i receive 400 error.
Could someone explain me how to get API URL in this situation like:
/api/tasks/{id}/operations
Thanks in advance.
Rather than passing the callback to the result of the function, you could just return the data.
export const getOperations = async (id) => {
try {
const response = await fetch(`${API_URL}/tasks/${id}/operations`, {
headers: {
Authorization: API_KEY,
},
});
const data = await response.json();
if (data.error) {
throw new Error('Error!');
}
return data.data;
} catch (err) {
console.log(err);
}
};
useEffect(() => {
async function apiCall() {
try {
const data = await getOperations(props.id);
setOperations(data)
} catch(err) {
console.log(err)
}
}
apiCall();
}, [props.id])

Fetch data from API with multiple React hook useEffect when second fetch use data from first hook

I'm learning how to use Hooks and I'm trying to fetch data from 2 sources with 2 hooks when the 2nd hook take as parameter the result from 1rst hook.
I know you can do that with class (multiple axios get) but I'm trying to do it with hooks.
I have a file where I've built my axios.get and a file where I try to render the data.
I try to put {user.id} into the second hooks but it doesn't work. When I put the value of the user id (for example '1') in the second hook it's working.
Long story short I try to find the best way to only show connected user objects...I'm not an expert so there is probably a better way to do that.
Any idea of how to do that ? Thanks for helping me !!!
Here is the code:
GetObjects.js:
export const getUser = async (id) => {
const url = `http://127.0.0.1:8000/api/user`;
try {
const response = await axios.get(url);
return { response, isError: false };
} catch (response) {
return { response, isError: true };
}
};
export const getUserObject = async (userId) => {
const url = `http://127.0.0.1:8000/api/objects/?owner=${userId}`;
try {
const response = await axios.get(url);
return { response, isError: false };
} catch (response) {
return { response, isError: true };
}
};
RenderObjects.js
...
function FetchUserObjects(props) {
const [objects, setObjects] = useState([]);
const [user, setuser] = useState([]);
useEffect(() => {
const loadUser = async () => {
const { response, isError } = await getUser();
if (isError) {
setuser([]);
} else {
setuser(response.data);
}
};
loadUser();
}, []);
useEffect(() => {
const loadObjects = async () => {
const { response, isError } = await getUserObject();
if (isError) {
setObjects([]);
} else {
setObjects(response.data);
}
};
loadObjects();
}, []);
so this is not working :
const { response, isError } = await getUserObject({user.id});
But this is working :
const { response, isError } = await getUserObject(1);
Try it:
function FetchUserObjects(props) {
const [objects, setObjects] = useState([]);
const [user, setuser] = useState([]);
useEffect(() => {
const loadUser = async () => {
const { response, isError } = await getUser();
if (isError) {
setuser([]);
} else {
setuser(response.data);
}
};
loadUser();
}, []);
useEffect(() => {
if (!user) return
const loadObjects = async () => {
const { response, isError } = await getUserObject(user.id);
if (isError) {
setObjects([]);
} else {
setObjects(response.data);
}
};
loadObjects();
}, [user]);

Confused between promise and async/awaits

I'm a novice in Node JS. I practice promise and I successfully used it. What I understand is with using a promise you can hold the output and send resolve and reject. I used in database operation.
Then someone suggested me to use async/awaits. So here is my code which ran successfully the first time.
shop.js file
const models = require("../models");
const shopModel = models.Shop;
exports.checkShop = function(shopName) {
return new Promise((reslove, reject) => {
shopModel
.findOne({ where: { shop: shopName } })
.then(rs => {
if (rs) {
reslove(rs);
}
})
.catch(err => {
reject(err.toString());
});
});
};
And the file where i called this
const shopController = require("./shop");
exports.getInstall = function(req, res) {
const shop = req.body.shop;
if (!cn(shop)) {
shopController
.checkShop(shop)
.then(
shopCheck =>
function() {
if (shopCheck) {
res.send(`Welcome back ${shopCheck.shop}`);
} else {
//my else stuff
}
}
)
.catch(
e =>
function() {
res.state(500).send(e);
}
);
} else {
return res
.status(400)
.send(
"Missing shop parameter. Please add ?shop=your-development-shop.myshopify.com to your request"
);
}
};
And this is how I tried to replace it with async/awaits. But it does not work.
exports.checkShop = async function(shopName) {
try{
var rs = await shopModel.findOne({ where: { shop: shopName } });
if(rs){
return rs;
}
else{
return false;
}
}
catch(e){
return Promise.reject(new Error(400));
}
};
And the other file
exports.getInstall = function(req, res) {
const shop = req.body.shop;
if (!cn(shop)) {
var shopCheck = shopController.checkShop(shop);
try {
if (shopCheck) {
res.send(`Welcome back ${shopCheck.shop}`);
} else {
// else stuff
}
} catch (e) {
res.state(500).send(e);
}
} else {
return res
.status(400)
.send(
"Missing shop parameter. Please add ?shop=your-development-shop.myshopify.com to your request"
);
}
};
Every function with the async keyword before it will (explicitly or implicitly) return a promise.
So when you call shopController.checkShop you will either have to do something like
shopController.checkShop().then(.... )
or make getInstall an async function as well so that you can use await inside it.
exports.getInstall = async function(req, res) {
// other code here..
const result = await shopController.checkShop(shop);
//..
}
Edit:
If you want to make getInstall async and use await on checkShop you will have to catch the potential rejection using try {} catch like you did in checkShop.

Returning value of the key in AsyncStorage (getItem) instead of a promise

I want to use a value stored in the AsyncStorage in another function.
Here's my ValueHandler.js
import { AsyncStorage } from 'react-native';
export async function getSavedValue() {
try {
const val = await AsyncStorage.getItem('#MyStore:savedValue');
console.log("#getSavedValue", val);
return val;
} catch (error) {
console.log("#getSavedValue", error);
}
return null;
}
I made the above function getSavedValue() to get the value of the savedValue stored in the AsyncStorage.
import {getSavedValue} from '../lib/ValueHandler';
import Api from '../lib/Api';
export function fetchData() {
return(dispatch, getState) => {
var params = [
'client_id=1234567890',
];
console.log("#getSavedValue()", getSavedValue());
if(getSavedValue() != null) {
params = [
...params,
'savedValue='+getSavedValue()
];
}
params = params.join('&');
console.log(params);
return Api.get(`/posts/5132?${params}`).then(resp => {
console.log(resp.posts);
dispatch(setFetchedPosts({ post: resp.posts }));
}).catch( (ex) => {
console.log(ex);
});
}
}
How do I achieve this? I really wanted a simple method to save a value in the local storage and retrieve it simply when I need to make an API call.
Anyone got any suggestions or solutions to this?
Try this:
Adding async to return (dispatch, getState) => { so you can await in it
import {getSavedValue} from '../lib/ValueHandler';
import Api from '../lib/Api';
export function fetchData() {
return async (dispatch, getState) => {
let params = [
'client_id=1234567890',
];
const val = await getSavedValue();
if (val != null) {
params = [...params, 'savedValue='+val];
// why not
// params.push(`savedValue=${val}`);
//
}
params = params.join('&');
return Api.get(`/posts/5132?${params}`))
.then(resp => {
dispatch(setFetchedPosts({ post: resp.posts }));
})
.catch( (ex) => {
console.log(ex);
});
};
}
You can do something like this:
import { AsyncStorage } from 'react-native';
export async function getSavedValue() {
return new Promise ((resolve, reject) => {
try {
const val = await AsyncStorage.getItem('#MyStore:savedValue');
console.log("#getSavedValue", val);
resolve(val);
}catch (error) {
console.log("#getSavedValue", error);
reject(error)
}
})
}
import {getSavedValue} from '../lib/ValueHandler';
import Api from '../lib/Api';
export function fetchData() {
return async (dispatch, getState) => {
var params = [
'client_id=1234567890',
];
console.log("#getSavedValue()", getSavedValue());
if(getSavedValue() != null) {
params = [
...params,
'savedValue='+ await getSavedValue()
];
}
params = params.join('&');
console.log(params);
return Api.get(`/posts/5132?${params}`).then(resp => {
console.log(resp.posts);
dispatch(setFetchedPosts({ post: resp.posts }));
}).catch( (ex) => {
console.log(ex);
});
}
}

Categories