簡體   English   中英

未捕獲(承諾)錯誤:對 fetch() 的掛鈎調用無效

[英]Uncaught (in promise) Error: Invalid hook call on fetch()

我正在為 Django 開發一個網絡應用程序。這是一個簡單的博客。 前端是在 React 和 Materials UI 中構建的,它基於此處的教程,但我不得不自己進行很多調整,因為他使用的是面向類的方法,其中許多方法已被棄用,因為 React 似乎是朝着基於 model 的 function 邁進。在演示者創建的 model 中,我們通過使用生成 JSON 對象將數據從我們的反應前端傳遞到我們的 django 后端,882765404344488 序列化。 我建立了一個博客文章提交表單,但由於我無法理解的原因而無法正常工作。

創建BlogPost.js

import React, { Component } from "react";
import Grid from "@mui/material/Grid";
import { FormControl, FormHelperText, TextField, Typography, Button } from "@mui/material";
import { Link } from "react-router-dom";
import { useState } from "react";
import { Navigate } from "react-router-dom";

export default function CreateBlogPost(props) {

  const[title,setTitle] = useState('');
  const[content,setContent] = useState('');
  const[tags, setTags] = useState('');

  const handleTitle = event => {
    setTitle(event.target.value);
  }
  const handleContent = event => {
    setContent(event.target.value);
  }
  const handleTags = event => {
    setTags(event.target.value);
  }

  const requestOptions = {
    method: "POST",
    headers: {'Content-Type': 'application/json'},
    body: JSON.stringify({
      title: title,
      content: content,
      tags: tags,
    })
  };

  const handlePostButtonPressed = (requestOptions) => {
    console.log(requestOptions)
    fetch("/blog/create",requestOptions)
    .then((response) => response.json())
    .then((data) => Navigate('/posts/' + data.postid));


  }

  return (
    <Grid container spacing={1} className="pl-2 pt-4">
      <Grid item xs={12}>
        <Typography component="h4" variant="h4">Create a post</Typography>
        <Grid item xs={12} className="-ml-2 mt-4">
          <FormHelperText>
            <div>Title:</div>
          </FormHelperText>
          <FormControl>
            <TextField required={true} type="text" value={title} onChange={handleTitle}/>
          </FormControl>
        </Grid>
        </Grid>
        <Grid item xs={12} className="-ml-2 mt-4">
          <FormHelperText>
            <div>Content:</div>
          </FormHelperText>
            <FormControl component="fieldset">
              <TextField required={true} type="text" value={content} onChange={handleContent}/>
            </FormControl>
        </Grid>
        <Grid item xs={12} className="-ml-2 mt-4">
          <FormHelperText>
            <div>Tags:</div>
          </FormHelperText>
            <FormControl component="fieldset">
              <TextField required={true} type="text" value={tags} onChange={handleTags}/>
            </FormControl>
        </Grid>
        <Grid item xs={12}>
          <Button color="primary" variant="contained" onClick={handlePostButtonPressed}>
            Post
          </Button>
          <Button color="secondary" variant="contained" to="/blogs/" component={Link}>
            Back
          </Button>
        </Grid>
    </Grid>
    )
  }

在我按下發布按鈕之前,這里的一切都正常工作。 在日志中,我看到我想提交的帖子的 JSON object 正確呈現(所以我知道這不是任何數據處理函數的錯誤),但我在獲取 function 時收到錯誤:

“未捕獲(承諾)錯誤:掛鈎調用無效。只能在 function 組件的主體內部調用掛鈎。這可能由於以下原因之一而發生:

  1. 您可能有不匹配的 React 版本和渲染器(例如 React DOM)
  2. 你可能違反了 Hooks 規則
  3. 你可能在同一個應用程序中有多個 React 副本”

我不相信我有不匹配的 React 版本。 這是我的 package.json:

{
  "name": "frontend",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "webpack watch --mode development ",
    "build": "webpack --mode production"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.20.7",
    "@babel/preset-env": "^7.20.2",
    "@babel/preset-react": "^7.18.6",
    "babel-loader": "^9.1.0",
    "glob-all": "^3.3.1",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "tailwindcss": "^3.2.4",
    "webpack": "^5.75.0",
    "webpack-cli": "^5.0.1"
  },
  "dependencies": {
    "@babel/plugin-proposal-class-properties": "^7.18.6",
    "@emotion/react": "^11.10.5",
    "@emotion/styled": "^11.10.5",
    "@mui/icons-material": "^5.11.0",
    "@mui/material": "^5.11.3",
    "autoprefixer": "^10.4.13",
    "css-loader": "^6.7.3",
    "draft-js": "^0.11.7",
    "postcss-cli": "^10.1.0",
    "postcss-loader": "^7.0.2",
    "react-draft-wysiwyg": "^1.15.0",
    "react-router-dom": "^6.6.1",
    "style-loader": "^3.3.1"
  }
}

我研究了這個問題,但未能找到解決方案。 我發現了其他構建 forms 的方法,但這會改變我的后端接收數據的方式。 除非絕對必要,否則我寧願避免這種情況。

問題

該代碼導入Navigate組件並嘗試直接調用它。

import { Navigate } from "react-router-dom";
export default function CreateBlogPost(props) {
  ...

  const handlePostButtonPressed = (requestOptions) => {
    console.log(requestOptions)
    fetch("/blog/create", requestOptions)
      .then((response) => response.json())
      .then((data) => Navigate('/posts/' + data.postid)); // <-- invoked here
  };

  ...

在 React 中,我們不直接調用/調用 React 組件,我們在 React 組件的渲染返回中將它們渲染為 JSX ,即<Navigate to="..." /> 通過將 React 組件直接調用為 function ,您打破掛鈎規則間接)。

Navigate是一個組件,在呈現時會影響聲明性導航操作,即導航到指定的路由路徑。 我確定您打算導入useNavigate掛鈎以使用navigate function 並在處理程序中執行命令式導航操作。

解決方案

導入useNavigate並發出命令式導航操作。 刪除requestOptions arg 並使用在requestOptions組件 scope 中聲明的 requestOptions。這是因為handlePostButtonPressed直接作為事件處理程序傳遞。

import { useNavigate } from "react-router-dom";
export default function CreateBlogPost(props) {
  const navigate = useNavigate();

  ...

  const requestOptions = {
    method: "POST",
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      title: title,
      content: content,
      tags: tags,
    })
  };

  const handlePostButtonPressed = () => {
    console.log(requestOptions)
    fetch("/blog/create", requestOptions)
      .then((response) => response.json())
      .then((data) => navigate(`/posts/${data.postid}`);
  };

  ...

  <Button
    color="primary"
    variant="contained"
    onClick={handlePostButtonPressed}
  >
    Post
  </Button>

  ...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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