I'm trying to call an async function in a callback in useEffect like this.
import {useState, useEffect} from 'react';
import Navbar from 'react-bootstrap/Navbar';
interface EnBoards {
id: number
name: string
uri: string
}
const RedichanNav = (): JSX.Element => {
const [enBoards, setEnBoards] = useState({});
useEffect(() => {
const fetchEnBoards = async () => {
const response = await fetch('/api/en-boards');
const enBoardsJson = await response.json() as EnBoards;
setEnBoards(enBoardsJson);
};
fetchEnBoards(); // Here
});
return (
<Navbar ></Navbar>);
};
export default RedichanNav;
Then I got an error.
20:5 error Promises must be awaited, end with a call to .catch, end with a call to .then with a rejection handler or be explicitly marked as ignored with the `void` operator
@typescript-eslint/no-floating-promises
Then I changed the code like this.
useEffect(async () => {
const fetchEnBoards = async () => {
const response = await fetch('/api/en-boards');
const enBoardsJson = await response.json() as EnBoards;
setEnBoards(enBoardsJson);
};
await fetchEnBoards();
});
Then I got another error.
14:13 error Effect callbacks are synchronous to prevent race conditions. Put the async function inside:
useEffect(() => {
async function fetchData() {
// You can await here
const response = await MyAPI.getData(someId);
// ...
}
fetchData();
}, [someId]); // Or [] if effect doesn't need props or state
Learn more about data fetching with Hooks: https://reactjs.org/link/hooks-data-fetching react-hooks/exhaustive-deps
My code is almost the same as FAQ and small demo and this article.
My .eslintrc.js
module.exports = {
env: {
browser: true,
es2021: true,
},
extends: [
'plugin:react/recommended',
'airbnb',
'airbnb/hooks',
'plugin:@typescript-eslint/recommended',
'plugin:@typescript-eslint/recommended-requiring-type-checking',
'prettier',
],
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaFeatures: {
jsx: true,
},
ecmaVersion: 12,
sourceType: 'module',
tsconfigRootDir: __dirname,
project: ['./tsconfig.json'],
},
plugins: [
'react',
'@typescript-eslint',
],
"ignorePatterns": [
".eslintrc.js"
],
rules: {
'semi': ['error', 'always'],
'no-use-before-define': "off",
"@typescript-eslint/no-use-before-define": "off",
'import/prefer-default-export': "off",
'import/extensions': [
'error',
{
js: 'never',
jsx: 'never',
ts: 'never',
tsx: 'never',
},
],
'react/jsx-filename-extension': [
'error',
{
extensions: ['.jsx', '.tsx'],
},
],
'react/react-in-jsx-scope': 'off',
'no-void': [
'error',
{
allowAsStatement: true,
},
],
"react/function-component-definition": [
2,
{
"namedComponents": "arrow-function"
}
]
},
settings: {
'import/resolver': {
node: {
paths: ['src'],
extensions: ['.js', '.jsx', '.ts', '.tsx']
},
},
},
};
Enmironment
- MacOS 12.5
- Node.js 18.7.0
- TypeScript 4.8.4
- React 18.2.0
- React-Bootstrap 2.5.0
- ESLint 8.25.0
- @typescript-eslint/eslint-plugin 5.39.0
- eslint-plugin-react-hooks 4.6.0
Thank you to read. Can anyone solve this?
CodePudding user response:
The first time you wrote the code it was right. Reading the error you got seems like you needed to add an try catch block to you function, like:
useEffect(() => {
const fetchEnBoards = async () => {
try { //This
const response = await fetch('/api/en-boards');
const enBoardsJson = await response.json() as EnBoards;
setEnBoards(enBoardsJson);
catch(err) {
console.log(err)
}
};
fetchEnBoards(); // Here
});
CodePudding user response:
Looks like you need to read async await
useEffect(() => {
const fetchEnBoards = async () => {
const response = await fetch('/api/en-boards');
const enBoardsJson = await response.json() as EnBoards;
setEnBoards(enBoardsJson);
};
fetchEnBoards()
.then((response)=>
console.log("In then block"))
.catch((err)=>
console.log("In catch block"))
});