I am quite new to coding in React/JS (or any async language for that matter) and am having trouble getting an API fetch function to return the result rather than the promise.
The fetch function is:
export const i_sGETOrg = async () => {
const Cookie = new Cookies();
await fetch(process.env.REACT_APP_APIADDRESS + "/api/v1/organizations/", {
method: "GET",
headers: {
Authorization: "Bearer " + Cookie.get("JWT"),
},
}).then((response) => {
response.json().then((result) => {
console.log(result);
return result;
});
})
.catch((error) => {
APIErrorHandler(error);
});
};
This is being called from an click handling function in a separate ponent:
const DevOrganisations = () => {
const [newOrganization, setNewOrganization] = useState("");
const [orgs, setOrgs] = useState([]);
//get the organisations for user when ponent mounts
useEffect(() => {
setOrgs(i_sGETOrg());
}, []);
//handle submit a new organization to API
const handleSubmit = (event) => {
event.preventDefault();
i_sPOSTCreateOrg(newOrganization);
};
//handle get list of organizations from API
const handleGetOrg = async () => {
setOrgs(i_sGETOrg());
console.log(orgs);
};
//handle log list of organizations to the console
const handleLogOrgs = () => {
console.log(orgs);
};
return (
<div className="container">
<h3>This is the development ORGANISATIONS page</h3>
<button onClick={handleGetOrg}>Get Organisations</button>
<button onClick={handleLogOrgs}>Console.log Orgs</button>
<form onSubmit={handleSubmit}>
<label>
Organization Name:
<input
type="text"
name="CreateOrgName"
value={newOrganization}
defaultValue=""
onChange={(e) => setNewOrganization(e.target.value)}
/>
</label>
<input type="submit" value="Submit" />
</form>
<p>Your org is:</p>
{newOrganization && <p>{newOrganization}</p>}
<OrgsListDisplay orgs={orgs} />
</div>
);
};
export default DevOrganisations;
How can I make handleGetOrg function wait for i_sGetOrg to return the result so setOrgs doesn't receive the promise? Or should I be tackling the state change pletely differently?
When I click the Get Organisations button the following is printed to the console:
Promise { <state>: "fulfilled", <value>: undefined }
DevOrganisations.js:27
Array(21) [ {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, … ]
Additionally, I added a button to get the orgs value, but this logs:
Promise { <state>: "fulfilled", <value>: undefined }
Any help with this would be greatly appreciated.
Thanks :)
Greg
I am quite new to coding in React/JS (or any async language for that matter) and am having trouble getting an API fetch function to return the result rather than the promise.
The fetch function is:
export const i_sGETOrg = async () => {
const Cookie = new Cookies();
await fetch(process.env.REACT_APP_APIADDRESS + "/api/v1/organizations/", {
method: "GET",
headers: {
Authorization: "Bearer " + Cookie.get("JWT"),
},
}).then((response) => {
response.json().then((result) => {
console.log(result);
return result;
});
})
.catch((error) => {
APIErrorHandler(error);
});
};
This is being called from an click handling function in a separate ponent:
const DevOrganisations = () => {
const [newOrganization, setNewOrganization] = useState("");
const [orgs, setOrgs] = useState([]);
//get the organisations for user when ponent mounts
useEffect(() => {
setOrgs(i_sGETOrg());
}, []);
//handle submit a new organization to API
const handleSubmit = (event) => {
event.preventDefault();
i_sPOSTCreateOrg(newOrganization);
};
//handle get list of organizations from API
const handleGetOrg = async () => {
setOrgs(i_sGETOrg());
console.log(orgs);
};
//handle log list of organizations to the console
const handleLogOrgs = () => {
console.log(orgs);
};
return (
<div className="container">
<h3>This is the development ORGANISATIONS page</h3>
<button onClick={handleGetOrg}>Get Organisations</button>
<button onClick={handleLogOrgs}>Console.log Orgs</button>
<form onSubmit={handleSubmit}>
<label>
Organization Name:
<input
type="text"
name="CreateOrgName"
value={newOrganization}
defaultValue=""
onChange={(e) => setNewOrganization(e.target.value)}
/>
</label>
<input type="submit" value="Submit" />
</form>
<p>Your org is:</p>
{newOrganization && <p>{newOrganization}</p>}
<OrgsListDisplay orgs={orgs} />
</div>
);
};
export default DevOrganisations;
How can I make handleGetOrg function wait for i_sGetOrg to return the result so setOrgs doesn't receive the promise? Or should I be tackling the state change pletely differently?
When I click the Get Organisations button the following is printed to the console:
Promise { <state>: "fulfilled", <value>: undefined }
DevOrganisations.js:27
Array(21) [ {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, … ]
Additionally, I added a button to get the orgs value, but this logs:
Promise { <state>: "fulfilled", <value>: undefined }
Any help with this would be greatly appreciated.
Thanks :)
Greg
Share Improve this question asked Mar 14, 2021 at 19:24 GregGreg 551 gold badge2 silver badges6 bronze badges 3-
1
fetch
always returns a Promise - that's by design, see eg developer.mozilla/en-US/docs/Web/API/Fetch_API You can't change that, you just need to work with the Promise it returns. (It couldn't possibly just return the response directly, because it's asynchronous.) – Robin Zigmond Commented Mar 14, 2021 at 19:29 - 1 LOTS of good general reading around these kinds of issues here – Robin Zigmond Commented Mar 14, 2021 at 19:31
- Fetch always returns a promise with the data in it, and that is how is was designed just as @RobinZigmond says however you can get the result by using await, await returns the resolved or rejected data which you can store it in a variable. – Naresh M Commented Oct 4, 2022 at 5:26
1 Answer
Reset to default 2Looks like is the issue is that you don't return the result of the fetch
request. fetch
returns a Promise
by design. You can either await
its resolved/rejected value or use a Promise
chain of then-ables. You should avoid mixing the two though.
export const i_sGETOrg = async () => {
const Cookie = new Cookies();
try {
const response = await fetch(process.env.REACT_APP_APIADDRESS + "/api/v1/organizations/", {
method: "GET",
headers: {
Authorization: "Bearer " + Cookie.get("JWT"),
},
});
const result = await response.json();
return result;
} catch(error) {
APIErrorHandler(error);
};
};
Alternatively you can directly return the Promise chain returned from the fetch
request. In this case i_sGETOrg
doesn't need to be declared async
and it still returns a promise that is settled later. Don't forget to return the next Promise from extracting the JSON data from the response.
export const i_sGETOrg = () => {
const Cookie = new Cookies();
return fetch(process.env.REACT_APP_APIADDRESS + "/api/v1/organizations/", {
method: "GET",
headers: {
Authorization: "Bearer " + Cookie.get("JWT"),
},
})
.then((response) => response.json())
.then((result) => {
console.log(result);
return result;
})
.catch((error) => {
APIErrorHandler(error);
});
};
You want to actually wait for this resolved response though.
//handle get list of organizations from API
const handleGetOrg = async () => {
setOrgs(await i_sGETOrg());
};
or
//handle get list of organizations from API
const handleGetOrg = () => {
i_sGETOrg().then(res => setOrgs(res));
};