【问题标题】:why are changes in localStorage not updated until refresh?为什么localStorage中的更改直到刷新才更新?
【发布时间】:2021-08-09 08:22:59
【问题描述】:

我是使用 localStorage 的新手,我正在尝试使用 localStorage 来存储登录状态,因此如果用户登录,则会出现注销按钮,如果用户注销,则会出现登录按钮。

如果在重定向之前调用 localStorage,为什么在重定向之前不更改它?当我单击登录组件中的登录按钮时,应该更新 localStorage 并且应该显示 app.js 中的注销导航栏链接,但在我刷新页面之前它不会显示。为什么会发生这种情况?如何在重定向到新页面时正确显示注销按钮?

login.component.js

    onSubmit(e) {
        e.preventDefault()
        this.userdata = {
            username: this.state.username,
            password: this.state.password,
        };
        services.userlogin(this.userdata).then(res => {
                if (this._isMounted) {
                    console.log("Is mounted")
                    if (res === "Successfully authenticated user") {
                        // store the user in localStorage
                        console.log("changed");
                        localStorage.setItem('loggedIn', "true") -> loggedIn is set to true
                        localStorage.setItem('isloggingIn', "false") -> isLoggingIn is set to false
                        localStorage.setItem('username', this.userdata.username)
                    }
                    this.setState({errormessage: res, username:'', password:''});
                }
                else {
                    console.log("Is unmounted")
                }
        })
    }
    error()
    {
        if (this.state.errormessage === "Successfully authenticated user") {
            // store the user in localStorage
            return (<Redirect from="/login-component" to={{pathname: '/ShopDetail', state: this.state}}/>); -> Redirects to ShopDetail page but logout button isn't shown 

        }
        else{
            return (<span className="span">{this.state.errormessage}</span>);
        }
    }
    render() {
        return (
            <div className="div">
                <Form onSubmit={this.onSubmit} className="formWidth">
                    <Form.Group className="group" controlId="Username">
                        <Form.Label style={{display: 'flex', justifyContent: 'center'}}>Username</Form.Label>
                        <Form.Control type="text" value={this.state.username} onChange={this.onChangeusername}/>
                        {this.state.usernameerrormessage.length > 0 &&
                        <span className="span">{this.state.usernameerrormessage}</span>}
                    </Form.Group>
                    <Form.Group className="group" controlId="Password">
                        <Form.Label style={{display: 'flex', justifyContent: 'center'}}>Password</Form.Label>
                        <Form.Control type="text" value={this.state.password} onChange={this.onChangepassword}/>
                        {this.state.passworderrormessage.length > 0 &&
                        <span className="span">{this.state.passworderrormessage}</span>}
                    </Form.Group>
                    <Button variant="danger" size="lg" block="block" type="submit"> Login </Button>
                </Form>
                {this.error()}

            </div>
        );
    }
};

APP.js

constructor(){
    this.state = {isLoggingIn: localStorage.getItem('isloggingIn'), isLoggedIn: localStorage.getItem('loggedIn') ;
}
componentDidMount() {
        this.setState({isLoggingIn: localStorage.getItem('isloggingIn'), isLoggedIn: localStorage.getItem('loggedIn') });
    }
const {isLoggingIn, isLoggedIn} = this.state;
<Nav className="ml-auto">
          <Nav>
               {isLoggedIn==="false" && isLoggingIn==="false" && <Link to={'/login-component'} onClick={this.login} className="nav-link">Login</Link>}
          </Nav>
          <Nav>
               {isLoggedIn==="false" && isLoggingIn==="false" && <Link to={'/createuser-component'} className="nav-link">Sign up</Link>}
          </Nav>
          <Nav>
               {isLoggedIn==="true" && isLoggingIn==="false" && <Link to={'/'} onClick={this.logout} className="nav-link">Logout</Link>} -> ***isLoggedIn is set to true and isLoggingIn is set to false in async userlogin function but the change is not reflected here unless the page is refreshed***
          </Nav>
   </Nav>

我已经尝试解决这个问题很多天了,但我真的不明白为什么会发生这种情况。

【问题讨论】:

  • 您没有更新 App.js 中的状态,对吧?设置 localStorage 项时需要在 App.js 中设置状态,否则 App.js 无法知道变化
  • 我没有添加那部分,但我正在使用 componentDidMount() 中的 setState 更新 App.js 中的状态。
  • 那么反问会是:当您更新子组件中的 localStorage 时,App.js 会重新挂载吗?提示:答案是否定的
  • 这是我的问题,如何使用更新后的 localStorage 重新渲染 app.js?

标签: javascript reactjs


【解决方案1】:

您可以将 App.js 中的函数引用传递给子组件。这个函数接受一个新的状态值并执行 setState。在子组件中,您可以使用新值调用此函数

【讨论】:

  • 你会通过props将带参数的函数通过路由传递给登录组件吗?我之前尝试过,但我无法将任何功能从我的父应用程序组件传递到登录子组件。
  • 您只需要传递函数名(引用),然后在子组件中使用参数调用函数
【解决方案2】:

localStorage 没有反应,所以在Successfully authenticated user 之后你需要setState

if (res === "Successfully authenticated user") {
    // store the user in localStorage
    console.log("changed");
    localStorage.setItem('loggedIn', "true") -> loggedIn is set to true
    localStorage.setItem('isloggingIn', "false") -> isLoggingIn is set to false
    localStorage.setItem('username', this.userdata.username)

    // calling this.setState here
    this.setState({
      loggedIn: true,
      isLoggingIn: false,
      username: this.userdata.username,
    });
}

但更好的选择是在 state 更改时更新 localStorage。我不是 React 方面的专家,不确定处理它的最佳方法是什么。

// set state on successful auth
if (res === "Successfully authenticated user") {
    // calling this.setState here
    this.setState({
      loggedIn: true,
      isLoggingIn: false,
      username: this.userdata.username,
    });
}

// update localStorage when state changes
componentDidUpdate(_, prevState) {
    if (prevState.loggedIn !== this.state.loggedIn) {
        localStorage.setItem('loggedIn', this.state.loggedIn)
    }
    ...
}

【讨论】:

  • 我需要更新 login.component.js 中的 localStorage,然后 app.js 将获取更新后的 localstorage 并在导航栏添加注销链接。我想要改变的状态是在 app.js 里面而不是 login.component.js。
猜你喜欢
  • 2016-02-13
  • 1970-01-01
  • 2023-03-24
  • 1970-01-01
  • 2019-06-03
  • 2021-01-29
  • 1970-01-01
  • 2011-04-24
  • 1970-01-01
相关资源
最近更新 更多