Update Component after post new item to the Database - fetch

I am playing around with Sveltekit and I am struggling a bit..
So my problem is, when I add something to the DB it works, but the new Item does not show in the list until i Refresh the page. My Code looks like:
index.js
import { connectToDatabase } from '$lib/db';
export const post = async ({ request}) => {
const body = await request.json()
console.log(body)
const dbConnection = await connectToDatabase();
const db = dbConnection.db;
const einkaufszettel = db.collection('Einkaufszettel')
await einkaufszettel.insertOne({
name: body.newArticle
});
const einkaufsliste = await einkaufszettel.find().toArray();
return {
status: 200,
body: {
einkaufsliste
}
};
}
export const get = async () => {
const dbConnection = await connectToDatabase();
const db = dbConnection.db;
const einkaufszettel = db.collection('Einkaufszettel')
const einkaufsliste = await einkaufszettel.find().toArray();
console.log(einkaufsliste)
return {
status: 200,
body: {
einkaufsliste,
}
};
}
and the Script of index.svelte
<script>
import Title from '$lib/title.svelte'
export let einkaufsliste = []
let newArticle = ''
const addArticle = async () => {
const res = await fetch('/', {
method: 'POST',
body: JSON.stringify({
newArticle
}),
headers: {
'Content-Type': 'application/json'
}
})
fetchArticles()
}
async function fetchArticles() {
const res = await fetch('/')
console.log(res.body)
}
</script>
In the Network Preview Tab the new Item is already added to the List.

As you can read here, you need to reassign the einkaufsliste after fetching the list of elements from the API.
You can do this in your fetchArticles method, like this:
async function fetchArticles() {
einkaufsliste = await fetch('/')
}

Related

Displaying data from SWAPI

I am trying to display film details from this API https://swapi.dev/api/films in NextJS but I keep getting an error. It has something to do with the getStaticPath function. I am using this code: any help welcome.
import fetch from 'isomorphic-unfetch';
export const getStaticPaths = async () => {
const res = await fetch('https://swapi.dev/api/films');
const data = await res.json();
console.log("This is " + JSON.stringify(data));
const paths = data.results.map(film => {
return {
params: { id: film.episode_id.toString() },
};
});
return {
paths,
fallback: false,
};
};
export const getStaticProps = async (context) => {
const id = context.params.id;
const res = await fetch(`https://swapi.dev/api/films` + id);
const data = await res.json();
return {
props: { film: data },
};
};
const Details = ({ film }) => {
return (
<div>
<h1>Episode {film.episode_id}</h1>
<h1>{film.title}</h1>
</div>
);
};
export default Details;
I am expecting the episode ID and title to display
enter image description here
I have tried taking 'results' out of 'data.results.map', so 'data.map' but just results in a error says data.map is not a function...I guess because data is an object not an array. But results is an array so I am still lost. I do think the issue lies here somewhere though...

How to call RTK mutations after first finishes

I am using REDUX-TOOLKIT-QUERY, Now I have a situation, I have to call one mutation. once that mutation returns a response, and I have to use that response in the other three mutations as a request parameter. How can we implement this in a proper way?
const [getSettings, { isLoading, data: Settings }] =useSettingsMutation();
const [getMenu] =useMenuMutation();
const [getServices] = useServicesMutation();
useEffect(() => {
const obj = {
Name: "someNme",
};
if (obj) getSettings(obj);
if (Settings?._id ) {
const id = settings._id;
getServices(id);
getMenu(id);
getServices(id);
}
}, []);
useMutation will return a promise, you can directly await this promise to get the return result:
const [getSettings, { isLoading, data: Settings }] = useSettingsMutation()
const [getMenu] = useMenuMutation()
const [getServices] = useServicesMutation()
useEffect(() => {
;(async () => {
try {
const obj = {
Name: 'someNme',
}
const data = await getSettings(obj).unwrap()
if (data._id !== undefined) {
const id = data._id
getServices(id)
getMenu(id)
getServices(id)
// ...
}
} catch (err) {
// ...
}
})()
}, [])

Solution to prefetch in a component on nextjs

I'm looking for a solution/module where I don't need to inject inital/fallback data for swr/react-query things from getServerSideProps. Like...
from
// fetcher.ts
export default fetcher = async (url: string) => {
return await fetch(url)
.then(res => res.json())
}
// getUserData.ts
export default function getUserData() {
return fetcher('/api')
}
// index.tsx
const Page = (props: {
// I know this typing doesn't work, only to deliver my intention
userData: Awaited<ReturnType<typeof getServerSideProps>>['props']
}) => {
const { data } = useSWR('/api', fetcher, {
fallbackData: props.userData,
})
// ...SSR with data...
}
export const getServerSideProps = async (ctx: ...) => {
const userData = await getUserData()
return {
props: {
userData,
},
}
}
to
// useUserData.ts
const fetcher = async (url: string) => {
return await fetch(url)
.then(res => res.json())
};
const url = '/api';
function useUserData() {
let fallbackData: Awaited<ReturnType<typeof fetcher>>;
if (typeof window === 'undefined') {
fallbackData = await fetcher(url);
}
const data = useSWR(
url,
fetcher,
{
fallbackData: fallbackData!,
}
);
return data;
}
// index.tsx
const Page = () => {
const data = useUserData()
// ...SSR with data...
}
My goal is making things related to userData modularized into a component.

Firebase react native loading issue

I'm new at react native and I try to build an mobile app. I'm using Firebase for applications. When I try to login, it stucks on the loading page. And getting this warning:
Setting a timer for a long period of time, i.e. multiple minutes, is a performance and correctness issue on Android as it keeps the timer module awake, and timers can only be called when the app is in the foreground. See https://github.com/facebook/react-native/issues/12981 for more info.
(Saw setTimeout with duration 3600000ms)
What should I do?
Also authentication code is here:
import { AsyncStorage } from 'react-native';
export const SIGNUP = 'SIGNUP';
export const LOGIN = 'LOGIN';
export const AUTHENTICATE = 'AUTHENTICATE';
export const LOGOUT = 'LOGOUT';
let timer;
export const authenticate = (userId, token, expiryTime) => {
return dispatch => {
dispatch(setLogoutTimer(expiryTime));
dispatch({ type: AUTHENTICATE, userId: userId, token: token });
};
};
export const signup = (email, password) => {
return async dispatch => {
const response = await fetch(
'https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=...',
{
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
email: email,
password: password,
returnSecureToken: true
})
}
);
if (!response.ok) {
const errorResData = await response.json();
const errorId = errorResData.error.message;
let message = 'Bir terslik var!';
if (errorId === 'EMAIL_EXISTS') {
message = 'Bu e-posta zaten kayıtlı!';
}
throw new Error(message);
}
const resData = await response.json();
console.log(resData);
dispatch(
authenticate(
resData.localId,
resData.idToken,
parseInt(resData.expiresIn) * 1000
)
);
const expirationDate = new Date(
new Date().getTime() + parseInt(resData.expiresIn) * 1000
);
saveDataToStorage(resData.idToken, resData.localId, expirationDate);
};
};
export const login = (email, password) => {
return async dispatch => {
const response = await fetch(
'https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=...',
{
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
email: email,
password: password,
returnSecureToken: true
})
}
);
if (!response.ok) {
const errorResData = await response.json();
const errorId = errorResData.error.message;
let message = 'Bir terslik var!';
if (errorId === 'EMAIL_NOT_FOUND') {
message = 'Böyle bir e-posta yok!';
} else if (errorId === 'INVALID_PASSWORD') {
message = 'Bu şifre geçersiz!';
}
throw new Error(message);
}
const resData = await response.json();
console.log(resData);
dispatch(
authenticate(
resData.localId,
resData.idToken,
parseInt(resData.expiresIn) * 1000
)
);
const expirationDate = new Date(
new Date().getTime() + parseInt(resData.expiresIn) * 1000
);
saveDataToStorage(resData.idToken, resData.localId, expirationDate);
};
};
export const logout = () => {
clearLogoutTimer();
AsyncStorage.removeItem('userData');
return { type: LOGOUT };
};
const clearLogoutTimer = () => {
if (timer) {
clearTimeout(timer);
}
};
const setLogoutTimer = expirationTime => {
return dispatch => {
timer = setTimeout(() => {
dispatch(logout());
}, expirationTime);
};
};
const saveDataToStorage = (token, userId, expirationDate) => {
AsyncStorage.setItem(
'userData',
JSON.stringify({
token: token,
userId: userId,
expiryDate: expirationDate.toISOString()
})
);
};

Puppeteer element is console.log'able but return undefined in puppeteer

I'm trying to crawl a webpage that has a h3 tag under an a tag. I'm getting the a tag just fine, but when trying to get the innerText of h3 I'm getting an undefined value.
This is what I'm trying to crawl:
const puppeteer = require('puppeteer');
const pageURL = "https://producthunt.com";
const webScraping = async pageURL => {
const browser = await puppeteer.launch({
headless: false,
arges: ["--no-sandbox"]
});
const page = await browser.newPage();
let dataObj = {};
try {
await page.goto(pageURL, { waitUntil: 'networkidle2' });
const publishedNews = await page.evaluate(() => {
const newsDOM = document.querySelectorAll("main ul li");
let newsList = [];
newsDOM.forEach(linkElement => {
const text = linkElement.querySelector("a").textContent;
const innerText = linkElement.querySelector("a").innerText;
const url = linkElement.querySelector("a").getAttribute('href');
const title = linkElement.querySelector("h3").innerText;
console.log(title);
newsList.push({
title,
text,
url
});
});
return newsList;
});
dataObj = {
amount: publishedNews.length,
publishedNews
};
} catch (e) {
console.log(e);
}
console.log(dataObj);
browser.close();
return dataObj;
};
webScraping(pageURL).catch(console.error);
Console log works great, but puppeteer throws:
Cannot read property 'innerText' of null
It looks like your solution is working just fine, but you're not controlling whether the h3 tag is null or not. Try adding an if statement before accessing the innerText attribute, or use the code I left below.
const puppeteer = require('puppeteer');
const pageURL = "https://producthunt.com";
const webScraping = async pageURL => {
const browser = await puppeteer.launch({
headless: false,
arges: ["--no-sandbox"]
});
const page = await browser.newPage();
let dataObj = {};
try {
await page.goto(pageURL, { waitUntil: 'networkidle2' });
const publishedNews = await page.evaluate(() => {
let newsList = [];
const newsDOM = document.querySelectorAll("main ul li");
newsDOM.forEach(linkElement => {
const aTag = linkElement.querySelector("a");
const text = aTag.textContent;
const innerText = aTag.innerText;
const url = aTag.getAttribute('href');
let title = aTag.querySelector("h3");
// there may be some <a> without an h3, control
// the null pointer exception here, accessing only
// if title is not 'null'.
if (title) title = title.innerText;
console.log(title);
// changed the object structure to add a key for each attr
newsList.push({
title: title,
text: text,
url: url
});
});
return newsList;
});
// changed the object structure to add a key for the array
dataObj = {
amount: publishedNews.length,
list: publishedNews
};
} catch (e) {
console.log(e);
}
console.log({receivedData: dataObj});
browser.close();
return dataObj;
};
webScraping(pageURL).catch(console.error);
Let me know if this fixes your problem!

Resources