类组件 ReactJS - setTimeout 在类组件中获取错误值

Class Component ReactJS - setTimeout get wrong value in class component

提问人: 提问时间:1/27/2023 更新时间:1/28/2023 访问量:89

问:

应用组件:

class App extends React.Component {
        constructor() {
          super();
            this.state = {
            user: 'Dan',
          };
        }
        render() {
          return (
            <React.Fragment>
              <label>
                <b>Choose profile to view: </b>
                <select
                  value={this.state.user}
                  onChange={e => this.setState({ user: e.target.value })}
                >
                  <option value="Dan">Dan</option>
                  <option value="Sophie">Sophie</option>
                  <option value="Sunil">Sunil</option>
                </select>
              </label>
              <h1>Welcome to {this.state.user}’s profile!</h1>
              <p>
                <ProfilePageClass user={this.state.user} />
                <b> (class)</b>
              </p>
            </React.Fragment>
          )
        }
      }

ProfilePageClass(问题就在这里):

class ProfilePageClass extends React.Component {
  showMessage = () => {
    alert('Followed ' + this.props.user); // This get wrong value (new props)
  };

  handleClick = () => {
    setTimeout(this.showMessage, 6000); // This get wrong value (new props)
  };

  render() {
    return <button onClick={this.handleClick}>Follow</button>;
  }
}

setTimeout 不显示最初关注的用户对应的消息

我认为这是道具的问题,但我不确定。

谁能告诉我这是怎么回事?

javascript reactjs 关闭 这个 react-props

评论

1赞 Bergi 1/27/2023
最初关注的用户”是什么意思?按钮不应该提醒被关注的用户的名称吗?
0赞 1/27/2023
是的,@Bergi,点击关注,setTimeout 需要一点时间(我故意这样做是为了看看是否有人可以向我解释),但它更改了道具并发出警报,因为应用程序在用户列表中发生了变化。
1赞 1/27/2023
例如,我们在“Dan”上给出了 follow,然后它被更改为 “Sunil”,消息应该转到第一个被关注的 “Dan”,但消息保留在 “Sunil” 上,这是选择组件被留下的地方。
0赞 1/27/2023
codesandbox.io/s/pjqnl16lm7 这就是我得到示例的地方

答:

-1赞 saguirrews 1/27/2023 #1

很可能你的使用存在问题,你失去了对你希望展示的实际道具的引用。您可以将类似以下内容添加到父组件中:setTimeout

this.myRef = React.createRef();

这将生成一个 ref,您稍后可以将其传递给子组件。您可以按以下方式设置 refs 当前项目:

this.myRef.current = this.state.user

为了填充 ref。

评论

0赞 1/27/2023
嗨,@saguirrews,谢谢,但是,我需要更多细节来理解
-1赞 Mallikarjun M G 1/27/2023 #2

尝试此修改,因为可能没有自动绑定。handleClick

import React from "react";
export default class App extends React.Component {

  constructor(props) {
    super(props);
      this.state = {
      user: 'Dan',
    };
  }
  render() {
    return (
      <React.Fragment>
        <label>
          <b>Choose profile to view: </b>
          <select
            value={this.state.user}
            onChange={e => this.setState({ user: e.target.value })}
          >
            <option value="Dan">Dan</option>
            <option value="Sophie">Sophie</option>
            <option value="Sunil">Sunil</option>
          </select>
        </label>
        <h1>Welcome to {this.state.user}’s profile!</h1>
        <p>
          <ProfilePageClass user={this.state.user} />
          <b> (class)</b>
        </p>
      </React.Fragment>
    )
  }
}

个人资料提醒

class ProfilePageClass extends React.Component {
//Define a constructor here
  constructor(props){
    super(props)
// Bind handleClick , so that `this` will point to parent component when you pass to child
    this.handleClick= this.handleClick.bind();
  }
  showMessage = () => {
    alert('Followed ' + this.props.user); // This get value (new props)
  };

  handleClick = () => {
    setTimeout(this.showMessage, 100); // This get  value (new props)
  };

  render() {
    return <button onClick={this.handleClick}>Follow</button>;
  }
}
0赞 Bergi 1/27/2023 #3

与关键字无关。当应用状态更改时,组件实例会收到新值,并且在它们更改后运行的回调将访问新值。这有时是可取的,有时不是。thispropssetTimeout

这是函数组件和组件之间的区别之一。若要获取单击按钮时呈现的用户配置文件,需要在单击(或呈现)按钮时明确记住它:

class ProfilePageClass extends React.Component {    
  handleClick = () => {
    const user = this.props.user;
//  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    setTimeout(() => {
      alert('Followed ' + this.props.user); // current value (wrong)
      alert('Followed ' + user); // old value (expected)
    }, 6000);
  };

  render() {
    return <button onClick={this.handleClick}>Follow</button>;
  }
}

使用函数组件,您不会出错(但是如果没有 useRef,访问当前值几乎是不可能的):

function ProfilePageClass({user}) {    
  const handleClick = () => {
    setTimeout(() => {
      alert('Followed ' + user); // old value (expected)
    }, 6000);
  };
  return <button onClick={this.handleClick}>Follow</button>;
}

评论

2赞 Bergi 1/27/2023
是的,箭头函数在 上形成一个闭包。请注意,在 JS 中,闭包甚至根本不捕获值(无论是引用值还是这些值的副本,甚至是深层副本/快照),它们捕获变量。虽然既不改变也不改变,所以这里等同于捕捉 indeed 的(参考)值。thisthisconst userthis
1赞 Bergi 1/27/2023
它捕获实时变量,无论当前值(对象/基元)是什么。变量没有类型,您可以将基元分配给当前包含对象的变量,反之亦然。
2赞 Bergi 1/27/2023
就其本身而言,由于箭头函数的工作方式。this
1赞 Bergi 1/27/2023
是的,请参阅答案的第一段:问题是 React 正在改变组件实例。.props
1赞 Bergi 1/27/2023
是的,它们捕获当前渲染的所有蚂蚁不可变变量。唯一的出路是.constuseRef