簡體   English   中英

無效的掛鈎調用。 鈎子只能在 function 組件的主體內部調用。 - 使用上下文

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM