英文:
Uncaught TypeError: isOpen is not a function
问题
我试图将我的基于类的组件转换为基于函数的组件,这是我在学习REACT时写的一段时间,但在转换过程中,出现了一个错误,提示isOpen不是一个函数,我有点不明白,因为我将其定义为状态并在handleToggle()中调用它,然后在组件的logo处调用它。
import React, { useState, useEffect } from "react";
import logo from "../images/logo.svg";
import { FaAlignRight } from "react-icons/fa";
import { Link } from "react-router-dom";
import Badge from '@mui/material/Badge';
import Menu from '@mui/material/Menu';
import MenuItem from '@mui/material/MenuItem';
export default function Navbar(){
const [anchorEl, setAnchorEl] = useState(null);
const open = Boolean(anchorEl);
const handleClick = (event) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
const [isOpen, setIsOpen] = useState(false); // 改为false
useEffect(() => {
handleToggle();
});
const handleToggle = () => {
setIsOpen(!isOpen); // 改为这种方式
};
return (
<nav className="navbar">
<div className="nav-center">
<div className="nav-header">
<Link to="/">
<img src={logo} alt="Beach Resort" />
</Link>
<button
type="button"
className="nav-btn"
onClick={handleToggle}
>
<FaAlignRight className="nav-icon" />
</button>
</div>
<ul
className={isOpen ? "nav-links show-nav" : "nav-links"}
>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/rooms">Rooms</Link>
</li>
</ul>
<Badge badgeContent={4} color="primary"
id="basic-button"
aria-controls={open ? 'basic-menu' : undefined}
aria-haspopup="true"
aria-expanded={open ? 'true' : undefined}
onClick={handleClick}
>
<i className="fa-solid fa-cart-shopping text-light"
style={{ fontSize: 25, cursor: "pointer" }}
></i>
</Badge>
</div>
<Menu
id="basic-menu"
anchorEl={anchorEl}
open={open}
onClose={handleClose}
MenuListProps={{
'aria-labelledby': 'basic-button',
}}
>
<MenuItem onClick={handleClose}>Profile</MenuItem>
<MenuItem onClick={handleClose}>My account</MenuItem>
<MenuItem onClick={handleClose}>Logout</MenuItem>
</Menu>
</nav>
);
}
主要的更改是将isOpen
的初始状态设置为false
,然后在handleToggle
函数中更新它的状态,而不是尝试将它当作函数来调用。这应该解决你遇到的问题。
英文:
I was trying to convert my class-based component to function based component, which I wrote some while when I was learning REACT, while converting this, I got an error that isOpen is not the function which I kinda dint get as I defined it as a state and called in handleToggle(), which is then being called at the logo of my component.
import React, { useState, useEffect } from "react";
import logo from "../images/logo.svg";
import { FaAlignRight } from "react-icons/fa";
import { Link } from "react-router-dom";
import Badge from '@mui/material/Badge';
import Menu from '@mui/material/Menu';
import MenuItem from '@mui/material/MenuItem';
export default function Navbar(){
const [anchorEl, setAnchorEl] = useState(null);
const open = Boolean(anchorEl);
const handleClick = (event) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
const [isOpen, setIsOpen] = useState(null);
useEffect(() =>{
handleToggle();
});
// state = {
// isOpen: false,
// };
const handleToggle = () => {
setIsOpen(isOpen() );
};
return (
<nav className="navbar">
<div className="nav-center">
<div className="nav-header">
<Link to="/">
<img src={logo} alt="Beach Resort" />
</Link>
<button
type="button"
className="nav-btn"
onClick={handleToggle}
>
<FaAlignRight className="nav-icon" />
</button>
</div>
<ul
className={isOpen ? "nav-links show-nav" : "nav-links"}
>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/rooms">Rooms</Link>
</li>
</ul>
<Badge badgeContent={4} color="primary"
id="basic-button"
aria-controls={open ? 'basic-menu' : undefined}
aria-haspopup="true"
aria-expanded={open ? 'true' : undefined}
onClick={handleClick}
>
<i className="fa-solid fa-cart-shopping text-light"
style={{ fontSize: 25, cursor: "pointer" }}
></i>
</Badge>
</div>
<Menu
id="basic-menu"
anchorEl={anchorEl}
open={open}
onClose={handleClose}
MenuListProps={{
'aria-labelledby': 'basic-button',
}}
>
<MenuItem onClick={handleClose}>Profile</MenuItem>
<MenuItem onClick={handleClose}>My account</MenuItem>
<MenuItem onClick={handleClose}>Logout</MenuItem>
</Menu>
</nav>
);
}
EVERY PIECE OF ADVICE WILL BE APPRECIATED
答案1
得分: 1
isOpen
是一个数值,不是一个函数。尝试使用 setIsOpen(p => !p)
。
英文:
isOpen
is a value, not a function. Try setIsOpen(p => !p)
答案2
得分: 1
useState
返回一个包含两个部分的数组:存储在状态中的值和用于更新它的函数。如果你调用 const [isOpen, setIsOpen] = useState(null)
,isOpen
是你的值(最初设置为 null
),而 setIsOpen
是用于更新它的函数。
当你写 const handleToggle = () => { setIsOpen(isOpen()) }
时,你试图调用一个 null
值,这是不可能的,因为它不是一个函数。这就是错误消息告诉你的内容。
如果你想要切换 isOpen
的值,你应该将 isOpen
声明为布尔值,然后使用 setIsOpen
传入 isOpen
的相反值:
const [isOpen, setIsOpen] = useState(false); // <= 最初将其设置为false
const handleToggle = () => {
setIsOpen(!isOpen); // <= 当它为false时,将其设置为true,当它为true时将其设置为false
};
然而,如果你在没有依赖数组的情况下在 useEffect
中调用 handleToggle
,就像你目前正在做的那样,它将在每次重新渲染时都被调用,这可能不是你想要的。你很可能希望在响应用户交互时调用它,比如响应HTML元素事件(如 onClick
)。否则,你应该重构你的代码,以向 useEffect
添加必要的依赖项。
英文:
useState
returns an array with two things: a value that is stored in state, and a function to update it. If you call const [isOpen, setIsOpen] = useState(null)
, isOpen
is your value (originally set as null
) and setIsOpen
is a function to update it.
When you write const handleToggle = () => { setIsOpen(isOpen() ) }
, you're trying to call a null
value, which is impossible because it's not a function. That's what the error message is telling you.
Given you want to toggle the value for isOpen
, what you should do instead is declare isOpen
as a boolean, and call setIsOpen
with the opposite of isOpen
:
const [isOpen, setIsOpen] = useState(false); // <= set this originally to false
const handleToggle = () => {
setIsOpen(!isOpen); // <= this will set isOpen as true when it is false, and false when it is true
};
However, if you call handleToggle
inside a useEffect
with no dependency array, like you're doing, it will be called every time there is a rerender, which is probably not what you want. You most likely want to call this in response to a user interaction - so in response to an HTML element event (like onClick
). Otherwise you should refactor your code to add the necessary dependencies to useEffect
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论