【问题标题】:Direct update on state change (React)状态变化的直接更新(React)
【发布时间】:2021-11-18 22:16:15
【问题描述】:

因此,我目前面临一个常见问题,即我的类组件中的状态值不会立即更改,而只会在渲染/刷新页面后更改。我有一个名为“auth”的状态,我想在单击“注销”时将其属性为 false。当用户按下“注销”按钮时,我想立即将身份验证状态设置为“假”,然后将它们重定向到登录页面。但我的问题是 this.state.auth 如果没有发生刷新/重新渲染,它仍然是正确的。请记住,它必须在如下所示的 Class 组件中工作。

import React, { Component, useEffect, useState} from 'react';
import { AuthContext } from '../Context/AuthContext';
    
class Home extends Component {
  state = {
    auth: true
  }

  handleLogOut = () => {
    localStorage.clear();
    sessionStorage.clear();
    this.setState({auth: false});  //Here it stays 'true' up until refresh ?
    this.props.history.push('/'); 
  }

  render() {
    return (
      <AuthContext.Provider value={this.state.auth}>
        <div>
          <button onClick = {this.handleLogOut}>Log out</button>
        </div>
      </AuthContext.Provider>
    );
  }
};
    
export default withRouter(Home);

【问题讨论】:

  • 状态更改是异步的。你不能也不应该改变这一点。真正的根本问题是.. 为什么您需要立即进行这种更改?您是否遇到了异步性质的问题?解释那个问题而不是对抗反应。
  • @JokesOnYou 我猜你想要useEffect 钩子,或者等效的类生命周期componentDidUpdate。虽然不清楚你想要什么。 AuthContext 不应该包裹HomePage 而不是相反吗?
  • @Evert,是的,我遇到了与状态更改的异步性质有关的问题。我需要将其设置为“假”,否则我的登录屏幕将拒绝渲染,因为上下文应该是 auth: false 才会发生。当立即更改该值以允许其他组件与我的 Context 值相应地工作时,感觉要顺畅得多。
  • @JokesOnYou 这是因为您重定向到/ 吗?您可能希望在 setState 上使用回调参数。这将在 值更改后调用。
  • @Urmzd,在我的情况下,它与上下文包装无关。是的,你可以说我想使用 compondentDidUpdate。但这是否意味着我仍然必须“刷新”页面才能正常工作?

标签: javascript reactjs use-state web-frontend


【解决方案1】:

在您的具体情况下,请使用componentDidUpdate

你可以这样使用它

componentDidUpdate(prevProps, prevState) {
  console.log(this.state) // Logs new state.
}

但是,我建议您转向功能组件,因为 componentDidUpdate 和类似的基于类的组件被视为遗留组件。

Resource

【讨论】:

  • 是的,功能组件似乎在存储数据方面带来了更大的灵活性。谢谢推荐!
【解决方案2】:
this.setState(
  { auth: false },
  () => this.props.history.push("/")
);

【讨论】:

  • OP,这是最直接的选项(尽管比使用 componentDidUpdate 更少声明性)。
  • 不要这样做....它并没有真正使用组件生命周期,也根本不会转化为函数组件逻辑,而函数组件是 React 的未来。
  • @DrewReese 如果您正在使用类组件,为什么还要费心让它们看起来像它们不是的东西(即函数组件)?类组件不再是首选方法,但它们仍然有效且受支持,在这里使用 setState 中的回调非常好。
  • @emeraldsanto 因为如果您不了解使用非常明确设计和命名的类方法/函数的组件生命周期,因为它们“太令人困惑”,那么您将有一段时间的挣扎在功能组件中。 setState 回调是一个逃生舱口,类似于forceUpdate。这个 specific 实例还不错,但它设置了一个可怕的优先级,可能会链接setState 回调,这些回调将进一步的状态更新排入队列,而不是您希望在组件生命周期结束时养成的习惯已经被误解了。
【解决方案3】:

我在这里为你创建了一个小沙盒演示:https://codesandbox.io/s/a-simple-react-router-v4-tutorial-forked-uznym

在 React 重新渲染组件之前,您的 handleLogOut 函数会将 auth 读取为 false。除非可能发生任何错误,否则您可以在 render 方法中记录状态并查看它在那里读取的内容。

  handleLogOut = () => {
    console.log(this.state.auth);
    localStorage.clear();
    sessionStorage.clear();
    this.setState({ auth: false }); //Here it stays 'true' up until refresh ?
    // this.props.history.push("/");
    console.log(this.state.auth);
  };

  render() {
    console.log(this.state.auth);
    ...
  }

【讨论】:

  • 很抱歉,但它看起来并没有改变任何东西。状态更新后仍会记录“真”
猜你喜欢
  • 1970-01-01
  • 2020-10-09
  • 2018-04-08
  • 2019-07-14
  • 2016-10-02
  • 2022-12-15
  • 1970-01-01
  • 1970-01-01
  • 2019-02-01
相关资源
最近更新 更多