首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么组件方法使用fetch和settingState响应时不会导致componentDidMount()?

为什么组件方法使用fetch和settingState响应时不会导致componentDidMount()?
EN

Stack Overflow用户
提问于 2019-08-20 12:27:43
回答 3查看 62关注 0票数 1

我希望根据用户连接状态和用户角色动态生成菜单。我有一个json文件,从该文件中输入了带有所有菜单选项的React应用程序。问题在于它确实提供了“登录”和“联系人”选项,这些选项不需要任何特定的角色,也不需要用户登录,但是当我使用App的login()方法登录时(在其中我使用了fetch API并在响应中设置了新的状态),它不会刷新菜单选项(这是在componentDidMount()方法中完成的)。它一直为我提供登录和联系选项。当用户连接时,我希望切换登录以进行注销。

我尝试了很多东西,但是在我的代码中放置日志和调试器,我注意到组件在setState () fetch操作中调用之后没有重新呈现,但是状态确实在发生变化。我很好奇为什么setState没有触发componentDidMount()?

menu.json

代码语言:javascript
运行
复制
[
    {
        "txt": "login",
        "idRole": null
    },
    {
        "txt": "logout",
        "idRole": null
    },
    {
        "txt": "register",
        "idRole": [
            1
        ]
    },
    {
        "txt": "profile",
        "idRole": [
            1,
            2,
            3
        ]
    },
    {
        "txt": "contact",
        "idRole": null
    }
]

App.js

代码语言:javascript
运行
复制
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
}

当用户没有登录时,他只能看到登录和联系人。在登录时,他可以看到注销,而不是登录、联系人和与他的角色相关的所有其他选择。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-08-20 12:32:41

没有什么会导致componentDidMount再次运行,它是一个生命周期钩子,它只在组件的生命周期中运行一次。componentDidMount中的所有内容将只运行一次(在第一次呈现之后),因此,如果您需要对执行命令式代码的更改作出反应,请查看componentDidUpdate。您还应该查看一下文档

票数 1
EN

Stack Overflow用户

发布于 2019-08-20 12:40:16

如前所述,当组件首次挂载时,componentDidMount只运行一次。如果在第一次挂载之后使用setState(),函数将不会响应它。如果您想这样做,也许您应该使用componentDidUpdate,它确实会对这种类型的更改作出反应。而且,你的代码还有另一个问题。如果您使用setState()并使用componentDidUpdate,那么它将再次更改状态,并再次调用该函数,直到程序崩溃。因此,如果您不想造成这种情况,也可以删除它或将其移动到一个新的componentDidMount函数中。

票数 0
EN

Stack Overflow用户

发布于 2019-08-20 13:25:12

感谢所有引导我使用componentDidUpdate()方法的人。这个修改过的代码帮助我实现了我想要的。将来,我将清理代码以删除justLoggedIn,因为这可能不是必要的,但如果没有这些代码,则会导致setState深度错误。

代码语言:javascript
运行
复制
    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 })
    }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57573671

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档