Reactjs 如何在React Native中使用componentWillUnmount?

Reactjs 如何在React Native中使用componentWillUnmount?,reactjs,react-native,Reactjs,React Native,如何使用componentWillUnmount,因为我收到了下面的警告。 当我使用componentWillUnmount时,有没有办法将状态显示设置为true? 您可以检查组件是否以这种方式安装,然后检查异步函数中的此变量,查看是否仍可以运行该函数,或者以其他方式取消该函数: componentDidMount () { this.showPosts(); } showPosts = async () => { var userID = awai

如何使用componentWillUnmount,因为我收到了下面的警告。 当我使用componentWillUnmount时,有没有办法将状态显示设置为true?

您可以检查组件是否以这种方式安装,然后检查异步函数中的此变量,查看是否仍可以运行该函数,或者以其他方式取消该函数:

  componentDidMount () {
        this.showPosts();
  }

  showPosts = async () => {

    var userID = await AsyncStorage.getItem('userID');

    fetch(strings.baseUri+"getPostWithUserID", {
        method: 'POST',
        headers: {
           Accept: 'application/json',
           'Content-Type': 'application/json'
        },
        body: JSON.stringify({ 
            "user_id": userID
        })
        })
        .then((response) => response.json())
        .then((responseJson) => {

          this.setState({show: false}); // If I comment this line, then I don't get the warning.

        })
        .catch((error) => {
            console.error(error);
        });
  }

您可以将某些内部组件对象属性用作-
isComponentMounted
,然后在异步操作回调期间检查它。

您在代码中混合了一些东西。使用this.showPosts()时,您正在使用await,但没有调用await。您也没有像
await
可以抛出的那样,将
await
包装在
try/catch

有几种方法可以解决在未安装的组件上设置状态的问题。尽管这是一种反模式,但最简单的方法是在
componentDidMount
中设置一个变量,并在
componentWillUnmount
中跟踪组件的装载状态

因此,让我们重构您的代码,使其更有意义

这就是您的
组件didmount
组件willunmount
现在的外观

componentDidMount() { 
  this.mounted = true;
}

componentWillUnmount() {
  this.mounted = false;
}

async asyncFunction {
  if(this.isMounted){
    setState(....);
  }else{
    return;
  }
}
更新
showPosts
,使其完全
async/await

async componentDidMount () {
  this._isMounted = true;
  await this.showPosts();
}

componentWillUnmount () {
  this._isMounted = false;
}
或者,如果我们使用您当前的ShowPost实现,它看起来是这样的,但是修复了等待过程中try/catch的不足

showPosts = async () => {
  try {
    var userID = await AsyncStorage.getItem('userID');
    let response = await fetch(strings.baseUri + 'getPostWithUserID', {
      method: 'POST',
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        'user_id': userID
      })
    });

    let responseJson = await response.json();
    if (this._isMounted) {
      this.setState({show: false});
    }
  } catch (err) {
    console.error(error);
  }
}

另一种选择是一旦做出承诺就立即取消承诺。本文以某种方式解释了如何执行此操作,在componentDidMount中设置状态而不在构造函数中设置初始状态不是一个好主意,因为它会触发额外的呈现,这可能会导致性能问题

从官方文件:

您可以在componentDidMount()中立即调用setState()。它将触发额外的渲染,但会在浏览器更新屏幕之前发生。这保证了即使在这种情况下render()将被调用两次,用户也不会看到中间状态。请谨慎使用此模式,因为它通常会导致性能问题。在大多数情况下,您应该能够在构造函数()中指定初始状态。但是,对于modals和工具提示这样的情况,当您需要在呈现取决于其大小或位置的对象之前测量DOM节点时,它可能是必需的


但这又回到了为什么要使用componentWillUnmount?这用于注销事件、推送通知、清理资源。

可能重复@Andrew。如果您能在我的场景中给出答案,是否可能?我无法理解如何使用你提供的链接中给出的内容。TIA:)问题是,如果组件被卸载,如何防止在异步操作中设置状态-所以我仍然认为是相关的say@MtgKha Jeskai是的,我知道这一点。我能阻止这个警告吗?这里->如果(this.isMounted),你有可能阻止它
应该正好在
setState
之前,而不是在fetchIt之前。它给我一个警告,isMounted已被弃用。如何做?您需要自己定义它,然后使用生命周期方法-componentDidMount(){this.isComponentMounted=true},componentWillUnmount(){this.isComponentMounted=false}控制它非常感谢你,安德鲁。它终于对我起作用了。但是我有一个问题,为什么我们要使用
这个来生成变量。我的意思是,你能告诉我这样做变量是写在哪里的吗?我只是在调用setState()之前检查了isMounted是否消除了警告。那么,您给我的解决方案是正确的方法还是黑客攻击?
this.isMounted()
已被弃用,将在将来某个时候删除。最好不要使用不推荐使用的函数。不,我的意思是,总体解决方案是这样的吗?因为文章说,
if(this.isMounted()){this.setState({})}
这消除了警告是的,这是一个有效的解决方案。文章说:对于任何升级代码以避免isMounted()的人来说,一个简单的迁移策略是自己跟踪挂载状态。只需在componentDidMount中将_isMounted属性设置为true,并在componentWillUnmount中将其设置为false,然后使用此变量检查组件的状态。因此,我们所做的是避免使用不推荐使用的API,并使用有效的解决方案。
showPosts = async () => {
  try {
    var userID = await AsyncStorage.getItem('userID');

    fetch(strings.baseUri + 'getPostWithUserID', {
      method: 'POST',
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        'user_id': userID
      })
    })
      .then((response) => response.json())
      .then((responseJson) => {
        if (this._isMounted) {
          this.setState({show: false}); // If I comment this line, then I don't get the warning.
        }
      })
      .catch((error) => {
        console.error(error);
      });
  } catch (err) {
    console.warn(err);
  }
}