当前位置: 首页 > 知识库问答 >
问题:

使用异步初始化的prop值设置受控输入的初始状态

杭英杰
2023-03-14

我有一个受控输入,它接受名为user的道具。该对象由其父组件传递给它,并在其中用观察者1异步初始化。

在父组件中:

onAuthStateChanged() {
  this.unregisterAuthObserver = onAuthStateChanged((user) => {
    this.setState({
      isSignedIn: Boolean(user),
      user,
    });
  });
}

我想用user.displayname填充受控输入的初始状态。类似下面的内容,这不应该是反模式,因为状态只依赖于构造上的prop用户

class ControlledInput extends Component {
  constructor(props) {
    super(props);

    const { user } = props;

    this.state = {
      displayName: user ? user.displayName : '',
    };
  }
}

当我刷新受控输入时,出现以下问题:

  1. user的值为undefined,因为观察者尚未触发。组件被构造并将displayname分配给''.
  2. 观察者激发,为用户分配一个复杂的对象,React重新呈现组件。这不会更改组件的状态,DisplayName仍然是''

我被困在如何利用组件生命周期方法来实现这一点上。对于这种情况是否有最佳实践?我应该依赖于异步道具,还是应该将观察者移到受控组件中?

我考虑过使用componentdidupdate()来确定何时分配user,但感觉很难。

当组件更新后,请将此作为对DOM进行操作的机会。这也是一个很好的地方做网络请求,只要你比较当前的道具和以前的道具(例如,如果道具没有改变,网络请求可能是不必要的)。

共有1个答案

谢宸
2023-03-14

不需要在构造函数中赋值。您应该使用提供给render方法的道具,并在提升状态模式之后处理对父级中状态的更新。然后流到子组件。

请参见下面的示例。“增量”按钮模拟异步调用。ControlledInput是只读显示,而ControlledInput2允许对反映在状态中的输入进行编辑。

class Parent extends React.Component {
  constructor(props) {
    super(props);

    this.handleClick = this.handleClick.bind(this);
    this.onInputChanged = this.onInputChanged.bind(this);

    this.state = {
      user,
      count: 1
    };
  }

  handleClick(e) {
    const { user, count } = this.state;

    this.setState({
      user: { ...user, displayName: `display ${count + 1}` },
      count: count + 1
    });
  }

  onInputChanged(name) {
    this.setState({
      user: Object.assign(user, { displayName: name })
    });
  }

  render() {
    const { user, count } = this.state;

    return (
      <div>
        <ControlledInput user={user} />
        <div>{user.displayName}</div>
        <div>Count: {count}</div>
        <button onClick={this.handleClick}>increment</button>
        <div>
          <ControlledInput2 onInputChanged={this.onInputChanged} user={user} />
        </div>
      </div>
    );
  }
}

const ControlledInput = ({ user }) => 
  <input type="text" value={user.displayName} />;

class ControlledInput2 extends React.Component {
  constructor(props) {
    super(props);
    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(e) {
    this.props.onInputChanged(e.target.value);
  }

  render() {
    const { user } = this.props;
    return (
      <input
        type="text"
        onChange={this.handleChange}
        value={user.displayName}
      />
    );
  }
}

const user = { displayName: undefined };

const props = { user };
const rootElement = document.getElementById("sample");
ReactDOM.render(<Parent {...props} />, rootElement);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.4.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.4.2/umd/react-dom.production.min.js"></script>
<div id="sample"></div>
 类似资料:
  • SOFABoot 提供了模块并行启动以及 Spring Bean 异步初始化能力,用于加快应用启动速度。本文介绍如何使用 SOFABoot 异步初始化 Spring Bean 能力以提高应用启动速度。 使用场景 在实际使用 Spring/Spring Boot 开发中,一些 Bean 在初始化过程中执行准备操作,如拉取远程配置、初始化数据源等等。在应用启动期间,这些 Bean 会增加 Spring

  • 问题内容: 我想以异步方式初始化模块,并提出一些想法。我需要具有Mongo集合列表和其他数据的DB对象,但是为了简洁起见,其中的文件列表确实有用。 我无法导出函数或类,因为我每次都需要返回相同的对象。 首先 想到的最简单的方法是分配给它,然后填充它: 不好的事情–我真的从外面不知道什么时候准备好列表,也没有检查错误的好方法。 *我想出的 *第二种 方法是继承并通知所有人数据库已准备就绪或发生了错误

  • 2)有没有另一种方法可以重写这个逻辑而不使用道具来设置状态? 父组件: 子组件

  • 我在尝试用异步数据初始化过滤器时遇到了麻烦。 过滤器非常简单,它需要将路径转换为名称,但要做到这一点,它需要一个对应数组,我需要从服务器获取该数组。 在返回函数之前,我可以在过滤器定义中做一些事情,但是异步方面阻止了这一点 使用promise可能是可行的,但我不清楚角度负载是如何过滤的。这篇文章解释了如何通过服务实现这样的魔力,但是对于过滤器也可以这样做吗? 如果有人对如何翻译这些路径有更好的想法

  • 当安装完成并首次启动 Navicat Monitor 时,浏览器会弹出并打开你的 Navicat Monitor 的网址“http://<your_ip_address>:<port_number>”。你需要在欢迎页面完成 Navicat Monitor 的基本配置。 【注意】<your_host_address> 是安装了 Navicat Monitor 的系统的主机名,以及 <port_num

  • 考虑以下代码 VS2013编译器发出以下警告: 警告C4351:新行为:数组“B::member”的元素将默认初始化1 这里有记载 使用C 11,并应用“默认初始化”的概念,意味着B. part的元素将不会被初始化。 但我认为,成员{}应该执行值初始化,而不是默认初始化。VS2013编译器是否损坏? 8.5美元/6 默认初始化类型为T的对象意味着:-如果T是(可能是cv限定的)类类型(第9条),则