我希望根据用户连接状态和用户角色动态生成菜单。我有一个json文件,从该文件中输入了带有所有菜单选项的React应用程序。问题在于它确实提供了“登录”和“联系人”选项,这些选项不需要任何特定的角色,也不需要用户登录,但是当我使用App的login()方法登录时(在其中我使用了fetch API并在响应中设置了新的状态),它不会刷新菜单选项(这是在componentDidMount()方法中完成的)。它一直为我提供登录和联系选项。当用户连接时,我希望切换登录以进行注销。
我尝试了很多东西,但是在我的代码中放置日志和调试器,我注意到组件在setState () fetch操作中调用之后没有重新呈现,但是状态确实在发生变化。我很好奇为什么setState没有触发componentDidMount()?
menu.json
[
{
"txt": "login",
"idRole": null
},
{
"txt": "logout",
"idRole": null
},
{
"txt": "register",
"idRole": [
1
]
},
{
"txt": "profile",
"idRole": [
1,
2,
3
]
},
{
"txt": "contact",
"idRole": null
}
]App.js
import React, { Component } from 'react'
import Header from 'container/Header.js'
import Footer from './container/Footer'
import Login from './container/Login'
import menu from '../json-form-file/menu.json'
export default class App extends Component {
constructor (props) {
super(props)
this.state = {
isMenuOpen: false,
isLoggedIn: false,
menu: null,
page: null,
user: null
}
this.toggleMenu = this.toggleMenu.bind(this)
this.selectPage = this.selectPage.bind(this)
this.login = this.login.bind(this)
this.logout = this.logout.bind(this)
}
toggleMenu () {
this.setState({ isMenuOpen: !this.state.isMenuOpen })
}
selectPage (event) {
this.setState({ isMenuOpen: !this.state.isMenuOpen, page: event.target.textContent })
const toggler = document.getElementsByClassName('toggler')[0]
toggler.checked = !toggler.checked
}
login (event) {
event.preventDefault()
const requestBody = createLoginRequestBody(Array.from(event.target.parentElement.children))
clearLoginFields(Array.from(event.target.parentElement.children))
if (requestBody.username !== undefined && requestBody.pwd !== undefined) {
fetch('www.someLoginUrl.login', {
method: 'post',
body: JSON.stringify(requestBody),
headers: { 'Content-Type': 'application/json'
}
})
.then(response => response.json())
.then(response => this.setState({ user: response, isLoggedIn: true, page: null }))
}
}
logout (event) {
event.preventDefault()
const toggler = document.getElementsByClassName('toggler')[0]
toggler.checked = !toggler.checked
this.setState({ user: null, isLoggedIn: false, page: null, isMenuOpen: !this.state.isMenuOpen })
}
componentDidMount () {
console.log('im mounting')
const newMenu = this.refreshMenuSelection(menu)
this.setState({ menu: newMenu })
}
refreshMenuSelection (list) {
const newMenu = []
list.map((item) => {
if (item.txt === 'login' && this.state.isLoggedIn === false) newMenu.push(item)
if (item.txt === 'logout' && this.state.isLoggedIn === true) newMenu.push(item)
if (item.idRole === null && item.txt !== 'login' && item.txt !== 'logout') newMenu.push(item)
if (this.state.user !== null && item.idRole.includes(this.state.user.id_role)) newMenu.push(item)
})
return newMenu
}
render () {
return (
<div>
<Header
menu={this.state.menu}
toggleMenu={this.toggleMenu}
selectPage={this.selectPage}
logout={this.logout}
color={this.state.isMenuOpen ? secondaryColor : primaryColor} />
{this.state.page === 'login' ? <Login login={this.login} /> : null}
<Footer color={this.state.isMenuOpen ? secondaryColor : primaryColor} />
</div>
)
}
}
const createLoginRequestBody = (inputs) => {
const requestObject = {}
inputs.map((input) => {
if (input.id === 'username') Object.assign(requestObject, { username: input.value })
if (input.id === 'pwd') Object.assign(requestObject, { pwd: input.value })
})
return requestObject
}当用户没有登录时,他只能看到登录和联系人。在登录时,他可以看到注销,而不是登录、联系人和与他的角色相关的所有其他选择。
发布于 2019-08-20 12:32:41
没有什么会导致componentDidMount再次运行,它是一个生命周期钩子,它只在组件的生命周期中运行一次。componentDidMount中的所有内容将只运行一次(在第一次呈现之后),因此,如果您需要对执行命令式代码的更改作出反应,请查看componentDidUpdate。您还应该查看一下文档
发布于 2019-08-20 12:40:16
如前所述,当组件首次挂载时,componentDidMount只运行一次。如果在第一次挂载之后使用setState(),函数将不会响应它。如果您想这样做,也许您应该使用componentDidUpdate,它确实会对这种类型的更改作出反应。而且,你的代码还有另一个问题。如果您使用setState()并使用componentDidUpdate,那么它将再次更改状态,并再次调用该函数,直到程序崩溃。因此,如果您不想造成这种情况,也可以删除它或将其移动到一个新的componentDidMount函数中。
发布于 2019-08-20 13:25:12
感谢所有引导我使用componentDidUpdate()方法的人。这个修改过的代码帮助我实现了我想要的。将来,我将清理代码以删除justLoggedIn,因为这可能不是必要的,但如果没有这些代码,则会导致setState深度错误。
login (event) {
event.preventDefault()
const requestBody = createLoginRequestBody(Array.from(event.target.parentElement.children))
clearLoginFields(Array.from(event.target.parentElement.children))
if (requestBody.username !== undefined && requestBody.pwd !== undefined) {
fetch('http://127.0.0.1:8080/user/login', {
method: 'post',
body: JSON.stringify(requestBody),
headers: { 'Content-Type': 'application/json'
}
})
.then(response => response.json())
.then(response => this.setState({ user: response, justLoggedIn: true, isLoggedIn: true }))
}
}
logout (event) {
event.preventDefault()
const toggler = document.getElementsByClassName('toggler')[0]
toggler.checked = !toggler.checked
this.setState({ user: null, justLoggedOut: true, isLoggedIn: false, isMenuOpen: !this.state.isMenuOpen })
}
componentDidMount () {
if (this.state.user === null) this.setState({ menu: this.refreshMenuSelection(menu) })
}
componentDidUpdate () {
if (this.state.user !== null && this.state.justLoggedIn) this.setState({ menu: this.refreshMenuSelection(menu), justLoggedIn: false, page: null })
if (this.state.user === null && this.state.justLoggedOut) this.setState({ menu: this.refreshMenuSelection(menu), justLoggedOut: false, page: null })
}https://stackoverflow.com/questions/57573671
复制相似问题