![](/img/trans.png)
[英]Error: Invalid hook call. Hooks can only be called inside of the body of a function component. (w/ Reactstrap)
[英]Invalid hook call. Hooks can only be called inside of the body of a function component. - useContext
我通過上下文 api 創建了一個名為 workspacesData 的空 object 變量,該上下文在應用程序中全局可用。 我正在嘗試將我的 api 數據設置為下面的助手 function 中的變量(getWorkspacesData)。
這個 function getWorkspacesData 然后在應用程序的另一個頁面上被調用,以便用戶想要拉入數據並將其顯示在頁面上。 問題是當用戶按下按鈕時,我收到錯誤“無效的掛鈎調用。掛鈎只能在 function 組件的主體內部調用。”
我知道問題是我在這個 function 中使用了 useContext 掛鈎,但我該如何解決這個問題? 因為我想使用全局可用的變量來設置數據。
getWorkspaces.js
import { useContext } from "react";
import { AppContext } from "../../../context/context";
import mavenlinkAPI from "../apiTools";
const GetWorkspaces = async (mavenlinkAccessToken) => {
const {setWorkspacesData} = useContext(AppContext);
try{
const data = await mavenlinkAPI(
'get',
'workspaces?token='+mavenlinkAccessToken,
);
console.log(data)
setWorkspacesData(data);
} catch (error) {
console.log(error)
}
}
export default GetWorkspaces;
MavenlinkPage.jsx
import { Container, Grid, Paper } from '@mui/material';
import React, {useContext, useEffect, useRef, useState} from 'react';
import { getAuth } from "firebase/auth";
import Fab from '@mui/material/Fab';
import AddIcon from '@mui/icons-material/Add';
import {SuccessSnackbar, ErrorSnackbar} from '../components/PopupSnackbar';
import { AppContext } from '../context/context';
import GetWorkspaces from '../helpers/api/mavenlink/getWorkspaces';
import GetTimesheets from '../helpers/api/mavenlink/getTimesheets';
import GetUsers from '../helpers/api/mavenlink/getUsers';
import CreateProject from '../helpers/api/mavenlink/createProject';
import GetMavenlinkAccessToken from '../helpers/api/mavenlink/getMavenlinkAccessToken';
import DummyDataHolder from '../components/dummyDataHolder';
// import { DataGrid } from '@material-ui/x-data-grid';
export const MavenlinkPage = () => {
const { mavenlinkConnected } = useContext(AppContext);
const [errorAlert, setErrorAlert] = useState(false);
const [successAlert, setSuccessAlert] = useState(false);
const { mavenlinkAccessToken, setMavenlinkAccessToken } = useContext(AppContext);
const { workspacesData } = useContext(AppContext);
const auth = getAuth();
const user = auth.currentUser;
const uid = user.uid
const handleAlertClose = (event, reason) => {
if (reason === 'clickaway') {
return;
}
setSuccessAlert(false) && setErrorAlert(false);
};
useEffect(() => {
if(mavenlinkConnected){
GetMavenlinkAccessToken(setMavenlinkAccessToken);
}
}, [])
console.log(mavenlinkAccessToken)
return(
<>
<Container>
<div className="mavenlink-page">
<Grid container spacing={2}>
<Grid item xs={12}>
<h1>Mavenlink</h1>
</Grid>
<Grid item xs={12}>
<Paper className="connection-status" elevation={1}>
<h4 className="title">Connection Status:</h4>
{!mavenlinkConnected ? <h4 className="response-error">{user.email} is not connected</h4> : <h4 className="response-success">{user.email} is connected</h4>}
</Paper>
</Grid>
<Grid item xs={12}>
<Paper elevation={1}>
<h4>Get Workspaces</h4>
<Fab onClick={() => GetWorkspaces(mavenlinkAccessToken)} color="primary" aria-label="add">
<AddIcon />
</Fab>
<h4>Get timesheets</h4>
<Fab onClick={() => GetTimesheets(mavenlinkAccessToken)} color="primary" aria-label="add">
<AddIcon />
</Fab>
<h4>Get users</h4>
<Fab onClick={() => GetUsers(mavenlinkAccessToken)} color="primary" aria-label="add">
<AddIcon />
</Fab>
<h4>Create project</h4>
<Fab onClick={() => CreateProject(mavenlinkAccessToken)} color="primary" aria-label="add">
<AddIcon />
</Fab>
</Paper>
</Grid>
<Grid item xs={12}>
<Paper elevation={10} style={{ height: 400, width: '100%' }}>
{workspacesData != null ?
Object.keys(workspacesData).map((item, index) => {
return(
<div key={index}>
{workspacesData[item].map((m, ind) =>
<div key={ind}>{item}</div>
)}
</div>
)
})
:
<div></div>
}
</Paper>
</Grid>
</Grid>
</div>
{successAlert === true ? <SuccessSnackbar open={successAlert} handleClose={handleAlertClose}/> : <></> }
{errorAlert === true ? <ErrorSnackbar open={errorAlert} handleClose={handleAlertClose}/> : <></> }
</Container>
</>
);
};
您可以調用組件內部的鈎子並將其返回值傳遞給 function:
const getWorkspaces = async (mavenlinkAccessToken, onSuccess) => {
try{
const data = await mavenlinkAPI(
'get',
'workspaces?token='+mavenlinkAccessToken,
);
onSuccess?.(data)
} catch (error) {
console.log(error)
}
}
並將其稱為:
export const MavenlinkPage = () => {
const { setWorkspacesData } = useContext(AppContext);
...
onClick={() => getWorkspaces(mavenlinkAccessToken, setWorkspacesData )}
}
或者創建一個自定義鈎子:
const useGetWorkspaces = (mavenlinkAccessToken) => {
const { setWorkspacesData } = useContext(AppContext);
return async () => {
try{
const data = await mavenlinkAPI(
'get',
'workspaces?token='+mavenlinkAccessToken,
);
setWorkspacesData(data);
} catch (error) {
console.log(error)
}
}
}
並像這樣使用它:
export const MavenlinkPage = () => {
const getWorkspaces = useGetWorkspaces(mavenlinkAccessToken);
...
onClick={() => getWorkspaces()}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.