why i got an error in my handleClick async function? - javascript

i tried to add the display_1 and diplay_2 in my mutation variables and tried to console.log it but the output is (undefined, false, undefined) for the console.log(data,loading,error)
const CREATE_T09_SCREENSHOT = gql`
mutation
createT09ScreenShot(
$screenshot_window_1: String!,
$screenshot_window_2: String!,
) {
createT09ScreenShot(
screenshot_window_1: $screenshot_window_1,
screenshot_window_2: $screenshot_window_2,
) {
screenshot_window_1
screenshot_window_2
}
}
`;
const SaveLogsButton = () => {
const [createT09ScreenShot, { loading, error, data }] = useMutation(CREATE_T09_SCREENSHOT);
const handleClick = async () => {
const screenshotData = await saveImage();
if (screenshotData){
const { display_1, display_2 } = screenshotData;
createT09ScreenShot({
variables: {
screenshot_window_1: display_1,
screenshot_window_2: display_2,
},
});
}
console.log(data)
console.log(loading)
console.log(error)
};
i also tried to do this but it give me an error
const handleClick = async () => {
await saveImageFunction();
const { display_1, display_2 } = saveImage;
createT09ScreenShot({
variables: {
and here is the error
Unhandled Promise Rejection: TypeError: Right side of assignment cannot be destructured

I think you have some error inside handleclick function of saveImage destructurable object.
You need to replace your handleClick function code with this code:
const handleClick = async () => {
const screenshotData = await saveImageFunction();
const { display_1, display_2 } = screenshotData;
createT09ScreenShot({
variables: {
screenshot_window_1: display_1,
screenshot_window_2: display_2,
},
});
};

Related

How to set object hook properly in React?

I have these states:
const [maintenanceTypeId, setMaintenanceTypeId] = useState(null);
const [maintenanceId, setMaintenanceId] = useState(null);
const [addedId, setAddedId] = useState({
mainId : null,
mainTypeId : null,
});
I set states in these functions:
//setMaintenanceTypeId
//setAddedId
const addNewMainTypesList = async () => {
try {
const { data } = await axios.post(`${serverBaseUrl}/insertRowtoMainTypes`, {
description: newMaintenanceList.description,
title: newMaintenanceList.title
});
setMaintenanceTypeId(data[0]?.id);
console.log("MaintenanceTypeId", maintenanceTypeId);
//console.log("inserted type id",data[0]?.id);
setAddedId({...addedId, mainTypeId : maintenanceTypeId});
} catch (err) {
throw err;
}
const maintenanceList = await getMainTypes();
// console.log("main list", maintenanceList);
setMaintenanceList(maintenanceList);
};
//setMaintenanceId
//setAddedId
const addNewMainTypes = async () => {
try {
const { data } = await axios.post(`${serverBaseUrl}/insertRowtoMain`, {
nodeid: newMaintenance.nodeid,
maintenancetype: newMaintenance.maintenancetype,
personnel: newMaintenance.personnel,
process: newMaintenance.process,
date: newMaintenance.date,
});
setMaintenanceId(data[0]?.id);
console.log("MaintenanceId", maintenanceId);
setAddedId({...addedId, mainId : maintenanceId});
//console.log("inserted main id",data[0]?.id);
} catch (err) {
throw err;
}
I am console logging the addedId state in a submitHandler.
const submitHandler = (e) => {
e.preventDefault();
addNewMainTypesList();
getMain();
getMainTypes();
addNewMainTypes();
console.log("addedId",addedId);
}
Here is the console. As you can see, I can not get the maintenanceTypeId. How can I fix this?
setState is an asynchronous function. In other words, it won't directly update a given state.
In your case setMaintenanceTypeId is not directly updating maintenanceTypeId.
In order, to make it update directly, use inside of it an anonymous function, like this:
setMaintenanceTypeId(mTypeId => data[0]?.id);
It would be also better if you do the same for setAddedId (though not mandatory):
setAddedId(addedId => {...addedId, mainTypeId : maintenanceTypeId});
Let me know if this still doesn't work.

Uncaught ReferenceError: keyword is not defined at UseFetch.jsx and at Transactions.jsx

I am trying to load a website to my localhost but keep running into an error that says Uncaught ReferenceError: keyword is not defined at useFetch (:3000/src/hooks/useFetch.jsx:21:7) at TransactionsCard (:3000/src/components/Transactions.jsx:33:18). The issue hapens in my code where I'm fetching gifs from my API at giphy developer.
Here is the source code:
Transactions.jsx:
import React, { useEffect, useState } from "react";
import { ethers } from "ethers";
import { contractABI, contractAddress } from "../utils/constants";
export const TransactionContext = React.createContext();
const { ethereum } = window;
const createEthereumContract = () => {
const provider = new ethers.providers.Web3Provider(ethereum);
const signer = provider.getSigner();
const transactionsContract = new ethers.Contract(contractAddress, contractABI, signer);
return transactionsContract;
};
export const TransactionsProvider = ({ children }) => {
const [formData, setformData] = useState({ addressTo: "", amount: "", keyword: "", message: "" });
const [currentAccount, setCurrentAccount] = useState("");
const [isLoading, setIsLoading] = useState(false);
const [transactionCount, setTransactionCount] = useState(localStorage.getItem("transactionCount"));
const [transactions, setTransactions] = useState([]);
const handleChange = (e, name) => {
setformData((prevState) => ({ ...prevState, [name]: e.target.value }));
};
const getAllTransactions = async () => {
try {
if (ethereum) {
const transactionsContract = createEthereumContract();
const availableTransactions = await transactionsContract.getAllTransactions();
const structuredTransactions = availableTransactions.map((transaction) => ({
addressTo: transaction.receiver,
addressFrom: transaction.sender,
timestamp: new Date(transaction.timestamp.toNumber() * 1000).toLocaleString(),
message: transaction.message,
keyword: transaction.keyword,
amount: parseInt(transaction.amount._hex) / (10 ** 18)
}));
console.log(structuredTransactions);
setTransactions(structuredTransactions);
} else {
console.log("Ethereum is not present");
}
} catch (error) {
console.log(error);
}
};
const checkIfWalletIsConnect = async () => {
try {
if (!ethereum) return alert("Please install MetaMask.");
const accounts = await ethereum.request({ method: "eth_accounts" });
if (accounts.length) {
setCurrentAccount(accounts[0]);
getAllTransactions();
} else {
console.log("No accounts found");
}
} catch (error) {
console.log(error);
}
};
const checkIfTransactionsExists = async () => {
try {
if (ethereum) {
const transactionsContract = createEthereumContract();
const currentTransactionCount = await transactionsContract.getTransactionCount();
window.localStorage.setItem("transactionCount", currentTransactionCount);
}
} catch (error) {
console.log(error);
throw new Error("No ethereum object");
}
};
const connectWallet = async () => {
try {
if (!ethereum) return alert("Please install MetaMask.");
const accounts = await ethereum.request({ method: "eth_requestAccounts", });
setCurrentAccount(accounts[0]);
window.location.reload();
} catch (error) {
console.log(error);
throw new Error("No ethereum object");
}
};
const sendTransaction = async () => {
try {
if (ethereum) {
const { addressTo, amount, keyword, message } = formData;
const transactionsContract = createEthereumContract();
const parsedAmount = ethers.utils.parseEther(amount);
await ethereum.request({
method: "eth_sendTransaction",
params: [{
from: currentAccount,
to: addressTo,
gas: "0x5208", //21,000 gwei in hexadecimal form
value: parsedAmount._hex,
}],
});
const transactionHash = await transactionsContract.addToBlockchain(addressTo, parsedAmount, message, keyword);
setIsLoading(true);
console.log(`Loading - ${transactionHash.hash}`);
await transactionHash.wait();
console.log(`Success - ${transactionHash.hash}`);
setIsLoading(false);
const transactionsCount = await transactionsContract.getTransactionCount();
setTransactionCount(transactionsCount.toNumber());
window.location.reload();
} else {
console.log("No ethereum object");
}
} catch (error) {
console.log(error);
throw new Error("No ethereum object");
}
};
useEffect(() => {
checkIfWalletIsConnect();
checkIfTransactionsExists();
}, [transactionCount]);
return (
<TransactionContext.Provider
value={{
transactionCount,
connectWallet,
transactions,
currentAccount,
isLoading,
sendTransaction,
handleChange,
formData,
}}
>
{children}
</TransactionContext.Provider>
);
};
useFetch.jsx:
import { useEffect, useState } from 'react';
const API_KEY = import.meta.env.VITE_GIPHY_API;
const useFetch = () => {
const [gifUrl, setGifUrl] = useState("");
const fetchGifs = async () => {
try {
const response = await fetch(`https://api.giphy.com/v1/gifs/search?api_key=${API_KEY}&q=${keyword.split(" ").join("")}&limit=1`)
const { data } = await response.json();
setGifUrl(data[0]?.images?.downsized_medium?.url)
} catch (error) {
setGifUrl('https://metro.co.uk/wp-content/uploads/2015/05/pokemon_crying.gif?quality=90&strip=all&zoom=1&resize=500%2C284')
}
}
useEffect(() => {
if (keyword) fetchGifs();
}, [keyword]);
return gifUrl;
}
export default useFetch;
When I comment out the lines that use 'keyword' it launches with no errors. This is at lines 14, 18, and 58-62 of Transactions.jsx.
Any help would be greatly appreciated, thank you!
The problem here is that you have not define keyword inside your useFetch function.
If you are trying to pass the keyword from the place where you use useFetch then do something like below and use the useFetch like const gifUrl = useFetch(<keyword>)
import { useEffect, useState } from 'react';
const API_KEY = import.meta.env.VITE_GIPHY_API;
const useFetch = (keyword) => {
const [gifUrl, setGifUrl] = useState("");
const fetchGifs = async () => {
try {
const response = await fetch(`https://api.giphy.com/v1/gifs/search?api_key=${API_KEY}&q=${keyword.split(" ").join("")}&limit=1`)
const { data } = await response.json();
setGifUrl(data[0]?.images?.downsized_medium?.url)
} catch (error) {
setGifUrl('https://metro.co.uk/wp-content/uploads/2015/05/pokemon_crying.gif?quality=90&strip=all&zoom=1&resize=500%2C284')
}
}
useEffect(() => {
if (keyword) fetchGifs();
}, [keyword]);
return gifUrl;
}
export default useFetch;
or even try adding default value for key work like below.
const useFetch = (keyword = "some keyword") => {

how to setup react-i18n with hooks, getting TypeError: Cannot read property 'length' of undefined

Here's the code:
translations.ts
function useTranslate () {
const namespace = 'translation';
return {
languages: languages,
transform: (_languages_) => {
const _languages = {};
console.log(_languages_)
_languages_['data'].forEach(language => {
languages.forEach(i => {
if (!_languages[i.code]) { _languages[i.code] = { [namespace]: {} }; }
_languages[i.code][namespace][language['en']] = language[i.code];
});
});
return _languages;
},
getAll: () => Axios.get('/translations'),
initialize: (resources) => {
i18next
.use(initReactI18next)
.use(LanguageDetector)
.init({
fallbackLng: ['en'],
lng: localStorage.getItem('i18nextLng') || 'en',
detection: {
order: ['querystring', 'cookie', 'localStorage', 'sessionStorage', 'navigator', 'htmlTag', 'path', 'subdomain'],
lookupCookie: 'i18next',
lookupLocalStorage: 'i18nextLng',
lookupSessionStorage: 'i18nextLng',
lookupFromPathIndex: 0,
lookupFromSubdomainIndex: 0,
caches: ['localStorage'],
htmlTag: document.documentElement,
},
supportedLngs: languages.map(a => a.code),
resources,
debug: true,
ns: [namespace],
defaultNS: namespace
});
}
};
}
export default useTranslate;
index.tsx
const { t } = useTranslation();
const { getAll } = useUser();
const { getAllRooms } = useRoom();
const [userData, setUserData] = useState({});
const [roomData, setRoomData] = useState({});
useEffect(() => {
const source = axios.CancelToken.source();
let ignore = true;
(async function setUser() {
let userResponse = await getAll();
let roomResponse = await get();
if (ignore) {
setUserData(userResponse['data']);
setRoomData(roomResponse['data']);
}
})()
return () => {
ignore = false;
source.cancel();
};
}, []);
_app.tsx
import i18next from 'i18next';
import useTranslate from '#services/core/hooks/translations';
const { languages } = useTranslate();
When I try to reload the page, I'm getting the error TypeError: Cannot read property 'length' of undefined on the react hooks. also it has an error Warning: React has detected a change in the order of Hooks called by Home. also i18next: init: i18next is already initialized. You should call init just once!
there's another error which is the Error: Rendered more hooks than during the previous render.
pages/index.tsx
const { t } = useTranslation();
const [userData, setUserData] = useState({});
useEffect(() => {
const source = axios.CancelToken.source();
let ignore = true;
(async function setData() {
let userResponse = await getAll();
if (ignore) {
setUserData(userResponse['data']);
}
})()
return () => {
ignore = false;
source.cancel();
};
},[]);

React - How to use higher-level useState in imported functions

The following code (with some parts of it cut out for the sake of brevity) is working:
function AddressInputList({
isOpen,
inputValue,
highlightedIndex,
getItemProps,
getMenuProps
}: AutocompleteInputListProps) {
const [items, setItems] = useState<MarkerPoint[]>([])
const api = 'XXXX'
const fetchURL = `https://api.opencagedata.com/geocode/v1/json?key=${api}&q=${inputValue}&limit=5&pretty=1`
useEffect(() => {
async function fetchData() {
if (inputValue !== null && inputValue.length > 1) {
try {
const request = await axios.get(fetchURL)
const items = request.data.results.map((res: any) => {
return {
lat: res.geometry.lat,
lng: res.geometry.lng,
address: res.formatted
}
})
setItems(items)
} catch (error) {
console.error(error)
}
}
}
fetchData()
}, [inputValue])
return (/*Code cut out*/)
}
What I now would like to do is to refactor the code to make it more lean. So I will create a utility.ts-file in which I have the fetchData-function and I subsequently would like to import the fetchData-function into the initial AddressInputList-function:
utility.ts:
export async function fetchData(inputValue: string, fetchURL: string) {
if (inputValue !== null && inputValue.length > 1) {
try {
const request = await axios.get(fetchURL)
const items = request.data.results.map((res: any) => {
return {
lat: res.geometry.lat,
lng: res.geometry.lng,
address: res.formatted
}
})
setItems(items)
} catch (error) {
console.error(error)
}
}
}
Now my problem here is that I don't know how to make the useState-hook setItems available in utility.ts. I read somewhere that this could be done with props but I'm not sure how this would look like. A short example would be highly appreciated!
Just create a custom hook that would fetch data for you.
I wouldn't recommend to tie this hook to inputValue so much. Also that .map formatting does not feel universal too.
export function useFetchData(inputValue: string, fetchURL: string) {
const [items,setItems] = useState([]);
useEffect(() => {
async function fetchData() {
if (inputValue !== null && inputValue.length > 1) {
try {
const request = await axios.get(fetchURL)
const items = request.data.results.map((res: any) => {
return {
lat: res.geometry.lat,
lng: res.geometry.lng,
address: res.formatted
}
})
setItems(items)
} catch (error) {
console.error(error)
}
}
}
}, [inputValue]);
return items;
}
After that you can use this custom hook like so
const items = useFetchData(inputValue, "/api/<endpoint>);
I guess you could just pass setItems as a callback function, as a parameter to your fetchData function.
fetchData(inputValue: string, fetchURL: string, setItems) {
...
}

Redux Saga not started?

I've written these actions and the saga to listen for them.
export async function addToWishlistApi(id: number) {
console.log("addToWishlistApi HELLO CAN ANYBODY HEAR ME");
const res = await axios.get(WishlistUrls.add(id));
console.log(res);
}
export function* addToWishlistSaga({ id }: { id: number }): Saga<void> {
console.log("addToWishlistSaga HELLO CAN ANYBODY HEAR ME");
try {
const res = yield call(addToWishlistApi, id);
console.log(res);
const wishlist = yield call(getCurrentWishlist);
console.log("WISHLIST", wishlist);
if (wishlist.contains(id))
yield put({ type: DealActionTypes.wishlistSuccess });
} catch (error) {
console.log("ERROR", error);
}
}
export async function getCurrentWishlist(): Promise<number[]> {
const res = await axios.get(WishlistUrls.getWishlist);
console.log(res.data.includes("WISHLIST-2.HTML"));
const $ = cheerio.load(res.data);
const tags = $(".button.yith-wcqv-button");
const idStrings: string[] = [];
tags.each((i, tag) => {
idStrings.push(tag.attribs["data-product_id"]);
});
const wishlist = idStrings.map(n => Number(n));
return wishlist;
}
export default function* wishlistSaga(): Saga<void> {
yield all([
yield takeEvery(DealActionTypes.addToWishlistStart, addToWishlistSaga),
yield takeEvery(
DealActionTypes.removeFromWishlistStart,
removeFromWishlistSaga
)
]);
}
I'm trying to test with recordSaga
import { runSaga } from "redux-saga";
export default async function recordSaga(saga, initialAction) {
const dispatched = [];
await runSaga(
{ dispatch: action => dispatched.push(action) },
saga,
initialAction
).done;
return dispatched;
}
And here are my tests:
describe("addToWishlistSaga", () => {
const startAction: Type.AddToWishlistStartAction = {
type: Types.addToWishlistStart,
id: deal.id
};
const successAction: Type.WishlistSuccessAction = {
type: Types.wishlistSuccess
};
const failureAction: Type.AddToWishlistFailureAction = {
type: Types.addToWishlistFailure,
id: deal.id
};
fit("dispatches a success action on success", async () => {
const dispatched = await recordSaga(wishlistSaga, startAction);
expect(dispatched).toContainEqual(successAction);
});
xit("dispatches a failure action on failure", async () => {
mock.onGet(WishlistUrls.add(deal.id)).networkErrorOnce();
const dispatched = await recordSaga(wishlistSaga, startAction);
expect(dispatched).toContainEqual(failureAction);
});
});
});
The saga setup and test setup are identical to what I've used successfully in other projects, but for some reason addToWishlistSaga is never being run. None of the desperate log statements are being printed, and dispatched comes back empty.
What am I doing wrong here? My head is about to explode.

Categories

Resources