I am trying to use a callback function in my async code but I am getting the error "callback is not a function". What am I doing wrong? I created the callBack function separately and passed it to the async function as a parameter then called it my react component
function myCallBack() {
setTopicLoaded(true);
}
//async function
export function fetchGroupTopic(groupAdminId, myCallback) {
return async (dispatch) => {
dispatch(getTopic());
try {
const myTopic = [];
if (groupAdminId) {
const response = firestore
.collection("topic")
.where("adminId", "==", groupAdminId);
const data = await response.get();
data.docs.forEach((item) => {
let id = item.id;
let data = item.data();
myTopic.push({ id, ...data });
});
myCallback();
dispatch(setGroupTopic(myTopic));
}
} catch (error) {
console.log(error);
dispatch(getTopicFailure());
}
};
}
// calling it here
React.useEffect(() => {
if (myGroup.length) {
fetchGroupTopic(myGroup[0].adminId,myCallBack);
}
}, [id, submitted, myGroup]);
Related
I am trying to use a callBack function in my async code but I am getting the error "TypeError: callBack is not a function". What am I doing wrong? I created the callBack function separately and passed it to the async function as a parameter then called it my useEffect.
function callBack() {
setTopicLoaded(true);
}
function fetchGroupTopic(groupAdminId, callBack) {
return async (dispatch) => {
dispatch(getTopic());
try {
const myTopic = [];
if (groupAdminId) {
const response = firestore
.collection("topic")
.where("adminId", "==", groupAdminId);
const data = await response.get();
data.docs.forEach((item) => {
let id = item.id;
let data = item.data();
myTopic.push({ id, ...data });
});
callBack(); // the error is coming from this line //
dispatch(setGroupTopic(myTopic));
}
} catch (error) {
console.log(error);
dispatch(getTopicFailure());
}
};
}
React.useEffect(() => {
if (myGroup.length) {
fetchGroupTopic(myGroup[0].adminId, callBack);
}
}, [id, submitted, myGroup]);
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])
I'm trying to get a redux function to work, however, it throws me this error:
[TypeError: callback is not a function. (In 'callback(true, result)', 'callback' is undefined)]
The function is like this:
export function searchEvent(categories, privateEvent, eventName,
eventCity, eventHourStart, eventHourFinish, eventDayStart, eventDayFinish, callback) {
return async () => {
try {
const ref = firestore().collection('events');
if (categories.length > 0) {
const promises = [];
const allData = [];
categories.forEach(e => {
let query = ref.where(e.field, '==', e.value);
if (privateEvent) {
query = ref
.where(e.field, '==', e.value)
.where('isPrivateEvent', '==', true);
}
const promise = query.get().then(response => {
const data = response.docs.map(d => d.data());
let result = data;
...
allData.push(...result);
}).catch(error => {
console.log(error);
});
promises.push(promise);
});
console.log(allData);
Promise.all(promises).then(() => {
callback(true, allData);
});
} else {
let query = ref;
if (privateEvent) {
query = ref.where('isPrivateEvent', '==', true);
}
query.get().then(response => {
const data = response.docs.map(d => d.data());
let result = data;
...
console.log(result);
callback(true, result);
}).catch(error => {
console.log(error);
});
}
} catch (e) {
console.log(e);
}
};
}
However, I'm pretty sure that I'm passing a callback to said function, as I'm doing it like so:
dispatchSearchEvent(categories, privateEvent, name, city,
hourstart, hourfinish, daystart, dayfinish, (s, r) => {
...
});
So, why it tells me that 'callback' is not a function when I'm clearly passing a callback to it in order to make it work?
I'm still a newbie when it comes to react-redux stuff, so any help will be appreciated.
I have a customHook with using useEffect and I would like it to return a result once useEffect is done, however, it always return before my async method is done...
// customHook
const useLoadData = (startLoading, userId, hasError) => {
const [loadDone, setLoadDone] = useState(false);
const loadWebsite = async(userId) => {
await apiService.call(...);
console.log('service call is completed');
dispatch(someAction);
}
useEffect(() => {
// define async function inside useEffect
const loadData = async () => {
if (!hasError) {
await loadWebsite();
}
}
// call the above function based on flag
if (startLoading) {
await loadData();
setLoadDone(true);
} else {
setLoadDone(false);
}
}, [startLoading]);
return loadDone;
}
// main component
const mainComp = () => {
const [startLoad, setStartLoad] = useState(true);
const loadDone = useLoadData(startLoad, 1, false);
useEffect(() => {
console.log('in useEffect loadDone is: ', loadDone);
if (loadDone) {
// do something
setStartLoad(false); //avoid load twice
} else {
// do something
}
}, [startLoad, loadDone]);
useAnotherHook(loadDone); // this hook will use the result of my `useLoadData` hook as an execution flag and do something else, however, the `loadDone` always false as returning from my `useLoadData` hook
}
It seems in my useDataLoad hook, it does not wait until my async function loadData to be finished but return loadDone as false always, even that I have put await keyword to my loadData function, and setLoadDone(true) after that, it still returns false always, what would be wrong with my implementation here and how could I return the value correct through async method inside customHook?
Well...it seems to be working after I put the setLoadDone(true); inside my async method, not inside useEffect, although I am not sure why...
updated code:
// customHook
const useLoadData = (startLoading, userId, hasError) => {
const [loadDone, setLoadDone] = useState(false);
const loadWebsite = async(userId) => {
await apiService.call(...);
console.log('service call is completed');
dispatch(someAction);
setLoadDone(true);
}
useEffect(() => {
// define async function inside useEffect
const loadData = async () => {
if (!hasError) {
await loadWebsite();
}
}
// call the above function based on flag
if (startLoading) {
await loadData();
// setLoadDone(true); doesn't work here
}
}, [startLoading]);
return loadDone;
}
I'm trying to call an endpoint in an api that returns a value, I have a dream to call this fetch function inside another function, then save it to a variable.
But this returns a promise or if I get it working the function calls other things before the returned value.
Is the only way to do a timeout?
Here is a code example
async function someFetch() {
const res = await fetch("someurl");
const data = res.json();
return data;
}
function useFetched(someInput1, someInput2) {
const fetchedData = someFetch(); // need this input before anything else is called
const some_var = fetchedData + someInput1 + someInput2;
return some_var;
}
I've also tried to make the second function async and called await in front of someFetch(), but this returns a promise.
You need need to await the result of someFetch
async function useFetched(someInput1, someInput2){
const fetchedData = await someFetch() // need this input before anything else is called
const some_var = fetchedData + someInput1 + someInput2
return some_var
}
You cant make async useFetch[hook]. You need to use a callback here. The rough idea, you can pass setter function to useFetch to set value. And then can use that value.
Sample:
async function fetchTodo() {
const res = await fetch("someurl");
const data = res.json();
return data;
}
function useFetched(id, callback) {
useEffect(() => {
fetchTodo(id).then(data => {
console.log(data);
callback(data);
});
}, [id, callback]);
}
Working sample:
import React, { useEffect, useState } from "react";
async function fetchTodo(id) {
const res = await fetch("https://jsonplaceholder.typicode.com/todos/" + id);
const data = res.json();
return data;
}
function useFetched(id, callback) {
useEffect(() => {
fetchTodo(id).then(data => {
console.log(data);
callback(data);
});
}, [id, callback]);
}
export default function App() {
const [data, setData] = useState({});
useFetched(1, setData);
if (!data) return <h1>Loading...</h1>;
return (
<div className="App">
<h1>{JSON.stringify(data)}</h1>
</div>
);
}
Sandbox: https://codesandbox.io/s/misty-smoke-ls2y4?file=/src/App.js:0-607