我正在尝试根据用户是否登录来更改按钮。该功能由 MyNav.js 管理。如果用户已登录,我会显示退出按钮,否则,我会显示登录和注册按钮。如果您能指导我做错的部分,那就太好了。
警告:
Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
at LoginSigninModal (http://localhost:3000/static/js/main.chunk.js:530:81)
at MenuButtons
MyNav.js
import React, { useEffect, useState } from 'react'
import Nav from 'react-bootstrap/Nav'
import Navbar from 'react-bootstrap/Navbar'
// import NavDropdown from 'react-bootstrap/NavDropdown'
import { Link } from 'react-router-dom'
import Searchfield from '../product_search_components/Searchfield'
import LoginSignout from '../login_components/LoginSignout'
import MenuButtons from './MenuButtons'
export default function MyNav(props) {
var isSigned
if (localStorage.getItem('scs_user_logged_in')){
isSigned = true
}else{
isSigned = false
}
const [signedIn, setSignedIn] = useState(isSigned)
var menu
if (signedIn) {
menu = <LoginSignout setSignedIn={setSignedIn}/>
} else {
menu = <MenuButtons setSignedIn={setSignedIn}/>
}
useEffect(()=>{
},[signedIn])
return (
<Navbar bg="light" expand="lg">
<Navbar.Brand><span style={{ fontWeight: 'bold' }}>Test</span></Navbar.Brand>
<Navbar.Toggle aria-controls="basic-navbar-nav" />
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="mr-auto">
<Link className='nav-link' to="/">Home</Link>
<Link className='nav-link' to="/about">About</Link>
<Link className='nav-link' to="/todo">Todo</Link>
{/* <NavDropdown title="Dropdown" id="basic-nav-dropdown">
<NavDropdown.Item>Action</NavDropdown.Item>
<NavDropdown.Item>Another action</NavDropdown.Item>
<NavDropdown.Item>Something</NavDropdown.Item>
<NavDropdown.Divider />
<NavDropdown.Item>Separated link</NavDropdown.Item>
</NavDropdown> */}
</Nav>
</Navbar.Collapse>
<Searchfield search_item={props.search_item} setSearchItem={props.setSearchItem} />
{menu}
</Navbar>
)
}
MenuButtons.js
import LoginSigninModal from '../login_components/LoginSigninModal'
import LoginSignupModal from '../login_components/LoginSignupModal'
export default function MenuButtons(props) {
return (
<>
<LoginSigninModal {...props}/>
<LoginSignupModal />
</>
)
}
LoginSigninModal.js
import React, { useState, useEffect } from 'react'
import Button from 'react-bootstrap/Button'
import Modal from 'react-bootstrap/Modal'
import Form from 'react-bootstrap/Form'
import Alert from 'react-bootstrap/Alert'
import Spinner from 'react-bootstrap/Spinner'
import { baseURL } from './../assets/axiosInstance'
import axios from 'axios'
// import LoginSignupModal from './LoginSignupModal'
export default function LoginSigninModal(props) {
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
const [localSigned, setLocalSigned] = useState(false)
const [email, setEmail] = useState("")
const [password, setPassword] = useState("")
const errorEmail = false
const [apiCalling, setApiCalling] = useState(false)
const [messageOnSubmit, setMessageOnSubmit] = useState({
type: "",
message: ""
})
useEffect(() => {
props.setSignedIn(localSigned)
}, [localSigned, props])
function handleSubmit() {
setApiCalling(true)
const getData = async () => {
await axios.post(baseURL + 'auth/login', {
email: email,
password: password,
})
.then((response) => {
localStorage.setItem('scs_token', response.data['access_token'])
localStorage.setItem('scs_user', JSON.stringify(response.data['user']))
localStorage.setItem('scs_user_logged_in', true)
setLocalSigned(true)
setMessageOnSubmit({
type: "success",
message: "Login Successful"
})
})
.catch((error) => {
console.log(error.response.status)
if(error.response.status === 401){
setMessageOnSubmit({
type: "danger",
message: "Login failed due to wrong password."
})
}else if(error.response.status === 422){
setMessageOnSubmit({
type: "danger",
message: "Password needs to be at least 6 characters long."
})
}
})
.then(()=>{
setApiCalling(false)
})
}
getData()
}
return (
<>
<Button variant="primary" onClick={handleShow} style={{ marginLeft: '5px' }}>
Signin
</Button>
<Modal
show={show}
onHide={handleClose}
backdrop="static"
keyboard={false}
>
<Modal.Header closeButton>
<Modal.Title>Signin</Modal.Title>
</Modal.Header>
<Modal.Body>
<Form>
<Form.Group controlId="formBasicEmail">
<Form.Label>Email address</Form.Label>
<Form.Control value={email} onChange={(data) => setEmail(data.target.value)} type="email" placeholder="xyz@email.com" />
</Form.Group>
<Form.Group controlId="formBasicPassword">
<Form.Label>Password</Form.Label>
<Form.Control value={password} onChange={(data) => setPassword(data.target.value)} type="password" placeholder="Password" />
</Form.Group>
{(
messageOnSubmit['type'] !== ""
?
<Alert variant={messageOnSubmit['type']}>
{messageOnSubmit['message']}
</Alert>
:
"")}
<Button variant="primary" type="button" disabled={errorEmail} active={!errorEmail} onClick={handleSubmit}>Login {apiCalling && <Spinner animation="border" size="sm" />}</Button>
<Button variant="secondary" onClick={handleClose} style={{ marginLeft: "5px" }}>Close</Button>
</Form>
</Modal.Body>
<Modal.Footer>
</Modal.Footer>
</Modal>
</>
);
}
http://localhost:3000/static/js/main.chunk.js:530:81 -(来自警告消息)
function LoginSigninModal(props) {
_s();
const [show, setShow] = Object(react__WEBPACK_IMPORTED_MODULE_1__["useState"])(--error marked here--)(false);
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
答案 0 :(得分:0)
问题出在 LoginSigninModal.js 的以下代码块中
.then((response) => {
localStorage.setItem('scs_token', response.data['access_token'])
localStorage.setItem('scs_user', JSON.stringify(response.data['user']))
localStorage.setItem('scs_user_logged_in', true)
setLocalSigned(true)
setMessageOnSubmit({
type: "success",
message: "Login Successful"
})
})
当我成功登录后,我更改了 localSigned 状态。卸载登录模式组件。然后我尝试更新该组件上的消息。由于组件已卸载,因此出现错误。删除 setMessageonSubmit 或在 setMessageSubmit 之后调用 set setLocalSigned,即可解决问题。
正确的代码应该是:
.then((response) => {
localStorage.setItem('scs_token', response.data['access_token'])
localStorage.setItem('scs_user', JSON.stringify(response.data['user']))
localStorage.setItem('scs_user_logged_in', true)
setMessageOnSubmit({
type: "success",
message: "Login Successful"
})
setLocalSigned(true)
})
或
.then((response) => {
localStorage.setItem('scs_token', response.data['access_token'])
localStorage.setItem('scs_user', JSON.stringify(response.data['user']))
localStorage.setItem('scs_user_logged_in', true)
setLocalSigned(true)
})
答案 1 :(得分:-1)
在您的 LoginSigninModal
组件中,您应该在 useEffect 函数中调用您的 getData
,如下所示:
useEffect(() => {
getData();
},[]);