useEffect => .then returns undefined - react-hooks

I try to fetch the current offer price for my NFT project but i currently get undefined in this function
useEffect(() => {
returnsCurrentOfferPrice(NFT.tokenId)
.then((offer) => {
console.log(offer);
setReturnCurrentOfferPrice(offer);
})
.catch((error) => {
console.log('Current offer price error', error);
});
}, [NFT.tokenId]);
This is my use State Snippet
const [returnCurrentOfferPrice, setReturnCurrentOfferPrice] = useState(null);
This is how i retrieve the function into my UI
const returnsCurrentOfferPrice = async (tokenId) => {
await getCurrentOfferPrice(tokenId)
}
And finally this is how i retrieve the data from the blockchain
const getCurrentOfferPrice = async (tokenId) => {
const web3Modal = new Web3Modal();
const connection = await web3Modal.connect();
const provider = new ethers.providers.Web3Provider(connection);
const contract = signerOrProvider(provider);
const currentOfferPrice = await contract.getCurrentOfferAmount(tokenId);
const bigNumber = ethers.BigNumber.from(currentOfferPrice);
const currentOfferPriceInEther = ethers.utils.formatEther(bigNumber)
console.log('Current offer price', currentOfferPriceInEther );
return currentOfferPriceInEther;
}

Related

koa js backend is showing error - DB not connected -how to fix this issue

I am also trying different network connections it returns the same error. Please help I am stuck last 15 days in this error. Oh! last one thing my laptop IP is dynamically changing so what can I do know.
this is my mongoose connecter
const mongoose = require('mongoose')
const connection = () =>{
const str = 'mongodb://localhost:27017/524'
mongoose.connect(str , () =>{
console.log("Connection is successfull")
} )
}
module.exports = {connection }
this is server js
const koa = require('koa')
const cors = require('koa-cors')
const bodyParser = require('koa-parser')
const json = require('koa-json')
const {connection} = require('./dal')
const userRouter = require('./Router/userRouter')
const app = new koa()
const PORT = 8000
app.use(cors())
app.use(bodyParser())
app.use(json())
app.use(userRouter.routes()).use(userRouter.allowedMethods())
app.listen(PORT, ()=>{
console.log(`Server is running on port ${PORT}`)
connection();
})
this is modle class
const mongoose = require('mongoose')
const Schema = mongoose.Schema
const UserSchema = new Schema ({
name:{
type:String,
required:true
},
email:{
type:String,
required:true,
unique:true
},
password:{
type:String,
required:true
},
role:{
type: Number,
default: 0
}
},{
timestamps:true
})
const User = mongoose.model('User', UserSchema)
module.exports = User
this is login route
const KoaRouter = require('koa-router')
const { register, login ,getAll } = require('../API/userAPI')
const userRouter = new KoaRouter({prefix: '/user'})
userRouter.post('/register', register)
userRouter.post('/login', login)
userRouter.get ('/get' , getAll)
module.exports = userRouter;
this is my contraller
const UserModel = require('../models/user.model')
const bcrypt = require('bcrypt')
const register = async (ctx) => {
try{
const user = ctx.request.body
const {name, email, password, role} = user
if (!name || !email || !password){
return (ctx.body = { message: "fill" });
}
else{
const exist = await UserModel.findOne({email})
if(exist){
return (ctx.body = { message: "User already exists" });
}else{
const salt = await bcrypt.genSalt();
const hashpassword = await bcrypt.hash(password, salt)
const newUser = new UserModel({
name,
email,
password : hashpassword,
role
})
await newUser.save()
return (ctx.body = { message: "User Registered" });
}
}
}catch(err){
console.log(err.message)
return (ctx.body = { message: err.message });
}
}
const login = async (ctx) => {
try{
const {email, password} = ctx.request.body
const user = await UserModel.findOne({email})
if (!user){
return ( ctx.body = {message:"User does not exist"})
}
else {
const isMatch = await bcrypt.compare(password, user.password)
if (!isMatch) {
return (ctx.body = { message:"Wrong Password"})
}else{
return (ctx.body = { user})
}
}
}catch(err){
return (ctx.body= {err})
}
}
const getAll = async (ctx) => {
try{
const users = await UserModel.find()
return (ctx.body = users)
}catch(err){
return (ctx.body= {err})
}
}
module.exports = {register, login ,getAll}
.
how to fix this.any ideas.Can any body guide me with this scenario.

Argument of type 'Promise<T>' is not assignable to parameter of type 'SetStateAction<T>'

I'm trying to make an api call with an async function. The function is in a useEffect hook so that every time the "input" is changed by the user, it searches for a new array.
When the api function is called, it returns Promise
I though I had resolved this Promise when using async await and .then(res) ?
Here is the code:
export type SearchResults = {
art_type: string
Title: string
Culture: string
Nation: string
Nationality: string
artist_type: string
Artist: string
source_type: string
Abbr: string
Source: string
}[]
const App: NextPage = () => {
const [input, setInput] = useState('Gogh')
const [results, setResults] = useState<SearchResults | undefined>(undefined)
// const [errors, setErrors] = useState<Error | null>(null)
useEffect(() => {
const fetchData = async (input: string) => {
const data: SearchResults = await fetch(`http://localhost:8080/search/${input}`).then(res => {
return res.json()
})
return data
}
const data = fetchData(input)
setResults(data)
}, [input])
const searchHandler = (e: React.ChangeEvent<HTMLInputElement>) => {
if (e.target !== null) setInput(e.target.value.toLowerCase())
}
const deboucedSearchHandler = useMemo(() => debounce(searchHandler, 500), [])
Solved it by moving my fetchData declaration outside useEffect. Then I made the anon func used by .then() asynchronous and has the res.json() assigned to a variable with the await keyword.
const [input, setInput] = useState('Gogh')
const [results, setResults] = useState<SearchResults | undefined>(undefined)
// const [errors, setErrors] = useState<Error | null>(null)
const fetchData = async (input: string) => {
await fetch(`http://localhost:8080/search/${input}`).then(async res => {
const response: SearchResults = await res.json()
setResults(response)
})
}
useEffect(() => {
fetchData(input)
}, [input])
const searchHandler = (e: React.ChangeEvent<HTMLInputElement>) => {
if (e.target !== null && e.target.value !== '') setInput(e.target.value.toLowerCase())
}
const deboucedSearchHandler = useMemo(() => debounce(searchHandler, 450), [])

Deno oak websocket must have a method that returns an async iterator

I am trying to build up a WebSocket with oak (not the native deno one).
The following code is how I build the server.
import {Application, Router, Context, send } from "https://deno.land/x/oak#v10.6.0/mod.ts";
const runWS = async (ctx: Context, next: () => Promise<unknown>) => {
try{
const ws = await ctx.upgrade();
ws.onopen = () => {
chatConnection(ws);
};
ws.onclose = () => { console.log('Disconnected from the client!');};
}catch{await next();}
}
let sockets = new Map<string, WebSocket>();
const chatConnection = async (ws: WebSocket) => {
console.log('new websocket, ws: ',ws);
const uid = globalThis.crypto.randomUUID();
sockets.set(uid,ws);
console.log('socket: ',sockets);
for await (const ev of ws){
console.log('ev: ', ev);
}
}
export const wsRoutes = new Router()
.get('/ws', runWS);
But in the for loop (at the end), for ws it says Type 'WebSocket' must have a '[Symbol.asyncIterator]()' method that returns an async iterator.. What's the deal with this and how to fix it?
The error message is providing you with useful information: the WebSocket is not AsyncIterable, which means that it cannot be used with a for await...of loop.
Here is the type documentation for WebSocket in Deno. It is (for the most part) the same as the WHATWG standard WebSocket that is documented on MDN.
If your intention is to respond to incoming message events, you'll need to attach an event listener:
webSocket.addEventListener("message", (messageEvent) => {
// Do something in response to each message event
});
Additional:
Here's an observation based on the code you've shown, but not in response to your question:
It's probably more ergonomic to store the sockets as the keys of your map, and the associated state data in the values. (This is the inverse of what you've shown). Here's an example of why:
import {
Router,
type RouterMiddleware,
} from "https://deno.land/x/oak#v10.6.0/mod.ts";
// You seem to want to log data to the console.
// This function will help you easily log only certain properties of objects:
/**
* Functional implementation of the type utility
* [`Pick<Type, Keys>`](https://www.typescriptlang.org/docs/handbook/utility-types.html#picktype-keys)
*/
function pick<T, K extends keyof T>(
obj: T,
keys: readonly K[],
): Pick<T, K> {
const result = {} as Pick<T, K>;
for (const key of keys) result[key] = obj[key];
return result;
}
type SocketData = { id: string };
const socketMap = new Map<WebSocket, SocketData>();
// Do something when a connection is opened
function handleOpen(ev: Event, ws: WebSocket) {
const socketData: SocketData = { id: window.crypto.randomUUID() };
socketMap.set(ws, socketData);
console.log({
event: pick(ev, ["type"]),
socketData,
});
}
// Do something when an error occurs
function handleError(ev: Event, ws: WebSocket) {
const socketData = socketMap.get(ws);
console.log({
event: pick(ev, ["type"]),
socketData,
});
socketMap.delete(ws);
}
// Do something when a connection is closed
function handleClose(ev: CloseEvent, ws: WebSocket) {
ev.code; // number
ev.reason; // string
ev.wasClean; // boolean
const socketData = socketMap.get(ws);
console.log({
event: pick(ev, ["type", "code", "reason", "wasClean"]),
socketData,
});
socketMap.delete(ws);
}
// Do something when a message is received
// Change `unknown` to the type of message payloads used in your application.
// (for example, JSON messages are `string`)
function handleMessage(ev: MessageEvent<unknown>, ws: WebSocket) {
ev.data; // unknown
ev.lastEventId; // string
ev.ports; // readonly MessagePort[]
const socketData = socketMap.get(ws);
if (socketData) {
socketData.id; // string
}
console.log({
event: pick(ev, ["type", "data", "lastEventId", "ports"]),
socketData,
});
}
const webSocketMiddleware: RouterMiddleware<"/ws"> = async (ctx, next) => {
const ws = ctx.upgrade();
ws.addEventListener("open", (ev) => handleOpen(ev, ws));
ws.addEventListener("error", (ev) => handleError(ev, ws));
ws.addEventListener("close", (ev) => handleClose(ev, ws));
ws.addEventListener("message", (ev) => handleMessage(ev, ws));
await next();
};
export const router = new Router();
router.get("/ws", webSocketMiddleware);
This is my updated code. It avoids the problem entirely
import {Application, Router, Context, send } from "https://deno.land/x/oak#v10.6.0/mod.ts";
interface BroadcastObj{
name: string,
mssg: string
}
const runWS = async (ctx: Context, next: () => Promise<unknown>) => {
if(!ctx.isUpgradable){
ctx.throw(501);
}
const uid = globalThis.crypto.randomUUID();
try{
const ws = await ctx.upgrade();
ws.onopen = () => {
chatConnection(ws);
};
ws.onmessage = (m) => {
let mssg = m.data as string;
if(typeof(mssg) === 'string'){
chatMessage(JSON.parse(mssg));
}
};
ws.onerror = (e) => {console.log('error occured: ', e);};
ws.onclose = () => { chatDisconnect(uid);};
}catch{await next();}
}
let sockets = new Map<string, WebSocket>();
const chatConnection = async (ws: WebSocket, uid: string) => {
await sockets.set(uid,ws);
}
const chatMessage = async (msg: BroadcastObj) => {
await sockets.forEach((ws: WebSocket) => {
ws.send(JSON.stringify(msg));
});
}
const chatDisconnect = async (uid: string) => {
await sockets.delete(uid);
}
export const wsRoutes = new Router()
.get('/ws', runWS);

How make make await as useDispatch

Can you please explain why await on dispatch has no effect?.Use dispatch is synchronous by default. But is there any way to make it to async?
I have one issue by using dispatch and createAsyncthunk.I think it halts the render of other components. I may be wrong please suggest a better way to handle this rendering issue. I think dispatch is still synchronous.
//API services
const getPersonLists = async (query) => {
return await axios.get(`${endPoint}/person?page=${query.page}&perPage=${query.perPage}`);
};
const fetchPeronWithAsyncThunk = createAsyncThunk('userSlice/userList', async (query) => await getPersonLists(query));
//Slice
const userSlice = createSlice({
name: 'userSlice',
initialState: {
users: [],
loading: false,
},
extraReducers: {
[fetchPeronWithAsyncThunk.pending]: (state) => {
state.loading = true;
},
[fetchPeronWithAsyncThunk.rejected]: (state) => {
state.loading = false;
},
[fetchPeronWithAsyncThunk.fulfilled]: (state, action) => {
state.loading = false;
state.users = action.payload;
},
},
});
//Component
const MyComponent = () => {
const { users } = useUserList(); //selector
const dispatch = useDispatch();
const getList = async () => {
//await has no effect
await dispatch(fetchPeronWithAsyncThunk({ page: 1, perPage: 10 }));
};
return (
<div>
<button onClick={getList}>Fetch user</button>
<div>{users.length && users.map((user, index) => <div key={index}>{user?.name}</div>)}</div>
</div>
);
};
await at that point has exactly the effect you are waiting for.
But since you are in a closure your state will not update within your getList function.
You can get the result of the thunk in your code though:
const result = await dispatch(fetchPeronWithAsyncThunk({ page: 1, perPage: 10 })).unwrap();
Also, you should be using the builder notation for extraReducers. We will deprecate the object notation you are using soon.

React redux Thunk - Making two ajax call one after the other with the result from the first ajax call using fetch API

I am trying to make two ajax call one after the other , i.e with the result of the first call data , i am making the second call. I am trying to use thunk , but it is not happening , i am getting errors.
actions.js
const fetchedStateNameSucess = (json) => {
return {
type: 'FETCH_STATE_NAME_SUCCESS',
json
}
}
const fetchProvidersDetailsSuccess = (providersData) => {
return {
type: 'FETCH_PROVIDER_DETAILS_SUCCESS',
providersData
}
}
export const fetchProvidersDetails = (providerId) => {
return (dispatch) => {
const providerUrl = `http://someUrl`;
const stateClientCountUrl = `http://someUrl/${state}`;
fetch(providerUrl)
.then(response => response.json())
.then(json => dispatch(fetchProvidersDetailsSuccess(json)))
.then((stateValue = json[0].stateVal)
fetch(stateClientCountUrl)
dispatch(fetchedStateNameSucess(response)));
};
}
In the above call , fetch(providerUrl) , i am getting response where i am getting the stateval , how to use that in making the second call to fetch(stateClientCountUrl) which takes stateval as a parameter.
As Miguel said you can do your second query in .then() clause as well as you can use async/await syntax, something like this:
export const fetchProvidersDetails = providerId => {
return async dispatch => {
const providerUrl = `http://someUrl`;
try {
const response = await fetch(providerUrl);
const json = await response.json();
dispatch(fetchProvidersDetailsSuccess(json))
const stateClientCountUrl = `http://someUrl/${json[0].stateVal}`;
const response2 = await fetch(stateClientCountUrl);
const json2 = await response2.json();
dispatch(fetchedStateNameSucess(json2));
} catch (error) {
console.log('Error', error);
}
}
If you want to use values from the first call response for the second fetch call, you need to do the second fetch after the first one has succeeded, more or less like this:
export const fetchProvidersDetails = (providerId) => {
return (dispatch) => {
const providerUrl = `http://someUrl`;
const stateClientCountUrl = `http://someUrl/${state}`;
fetch(providerUrl)
.then(response => response.json())
.then(json => {
dispatch(fetchProvidersDetailsSuccess(json));
const stateValue = json[0].stateVal;
fetch(stateClientCountUrl)
.then(response => dispatch(fetchProvidersDetailsSuccess(response)));
})
}
Don't forget to add error handling there, both for HTTP status codes and for JavaScript errors (by adding corresponding catch clauses).

Resources