javascript - setState(…) : Can only update a mounted or mounting component. 这通常意味着您在未安装的组件上调用了 setState()。这是一个空操作

标签 javascript reactjs firebase react-native

Can only update a mounted or mounting component. This usually means you called setState, replaceState, or forceUpdate on an unmounted component. This is a no-op.

Please check the code for the Menu component.

我不知道发生了什么。我一直在我的项目中发现这个错误。我真的不明白这个错误,因为这个错误没有给我具体的信息。现在,我很困惑这个错误让我有点紧张

export default class Menu extends Component {
    constructor(){
        super();
        this.state = {
            user: {},
            loading: true,
            dataSource: new ListView.DataSource({rowHasChanged: (row1, row2) => row1 !== row2 }),
            items: [],
        }
    }
    componentDidMount(){
        AsyncStorage.getItem('userData').then((user) => {
            let userData = JSON.parse(user)
            this.setState({
                user: userData,
            })
        })
        firebase.database().ref('Posts').limitToLast(10).on('value', (snap) => {
            console.log('new', snap.val())
            snap.forEach((child) => {
                this.state.items.push({
                    title: child.val().title,
                    key: child.key,
                    author: child.val().authorName,
                    image: child.val().picture,
                    price: child.val().price,
                    description: child.val().description,
                    stock: child.val().stock,
                    authorId: child.val().authorId
                });
            });
            this.setState({ 
                dataSource: this.state.dataSource.cloneWithRows(this.state.items),
                loading:false
            });
        });
    }

    logOut(){
        AsyncStorage.removeItem('userData').then(() => {
            firebase.auth().signOut();
                this.props.navigation.navigate('Index')
        })
    }

    renderRow(data) {
        return (
        <View style={styles.listProduct} key={data.key}>
            <TouchableOpacity 
             onPress={() => this.props.navigation.navigate('Detail', {data})}
            >
            <Text style={styles.titleProduct}> {data.title} </Text>
            <Text style={styles.textProduct}>{data.author}</Text>
            <Image
             source={{ uri:data.image }}
             style={{
                height: 150,
                width: 150,
                alignSelf: 'center',
            }}
          />
        </TouchableOpacity>
        <View style={styles.postInfo}>
          <Text style={styles.textProduct}>Rp.{data.price}</Text>
        </View>
        </View>
        )
    }

    render(){
        if (this.state.loading){
            return <ActivityIndicator size="large" />
        }

        console.ignoredYellowBox = ['Remote debugger'];
        console.ignoredYellowBox = ['Setting a timer'];
        console.log(this.state.user)
        const { navigate } = this.props.navigation
        return(
            <ScrollView>
            <View style={styles.container}>
                <View style={styles.header}>
                    <TouchableOpacity onPress={()=> this.props.navigation.navigate('Checkout')}>
                    <Icon name='md-cart' size={30} color='#eee'/>
                    </TouchableOpacity>
                    <View>
                    <TouchableOpacity onPress={this.logOut.bind(this)}>                    
                    <Icon name='ios-log-out-outline' size={30} color='#eee' />
                    </TouchableOpacity>
                    </View>

                    <View style={styles.addItem}>
                    <TouchableOpacity onPress={() => this.props.navigation.navigate('Add')}>
                    <Icon name='md-add' size={30} color='#eee' />
                    </TouchableOpacity>
                    </View>               
                </View>

                    <ListView
                      dataSource={this.state.dataSource}
                      renderRow={this.renderRow.bind(this)}
                      enableEmptySections={true}
                      />
            </View>
            </ScrollView>
        )
    }
}

最佳答案

当您卸载组件时,您需要删除任何其他类型的监听器的事件监听器。尽管组件已卸载,但 Firebase 查询正在尝试更新状态事件。您可以使用 off移除 firebase 监听器的方法。

您的代码的另一个可能问题是您直接操作状态值。这不是一个好的做法。下面的代码是一个示例,说明您如何使用您已经尝试做的事情来实现类似的效果。

示例

onData = (snap) => {
  console.log('new', snap.val())
  snap.forEach((child) => {
    this.setState((prevState) => {
      const newState = Object.assign({}, prevState);
      newState.items.push({
        title: child.val().title,
        key: child.key,
        author: child.val().authorName,
        image: child.val().picture,
        price: child.val().price,
        description: child.val().description,
        stock: child.val().stock,
        authorId: child.val().authorId
      });
      return newState;
    });
  });
  this.setState({ 
    dataSource: this.state.dataSource.cloneWithRows(this.state.items),
    loading:false
  });
}

componentDidMount(){
    AsyncStorage.getItem('userData').then((user) => {
        let userData = JSON.parse(user)
        this.setState({
            user: userData,
        })
    })
    firebase.database().ref('Posts').limitToLast(10).on('value', this.onData );
}

componentWillUnmount() {
  firebase.database().ref('Posts').limitToLast(10).off('value', this.onData );
}

关于javascript - setState(…) : Can only update a mounted or mounting component. 这通常意味着您在未安装的组件上调用了 setState()。这是一个空操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46831074/

相关文章:

javascript - React setState() 返回什么?

javascript - 如何在每次渲染之前重置 UseEffect React Hooks 中的数据?

javascript - Warning : setState(. ..): Can only update a mounted or mounting component on a new reactjs app

javascript - firestore 查询中的条件 where 子句

java - 解包数据 firestore 查询返回的数组类型

firebase - 错误 400 : unable to create collection using Firestore rest API

javascript - 为什么此代码显示不正确的 Unicode?

php - 使用 jquery 替换 youtube 嵌入代码中的字符串

javascript - 如何在 JS 中检查 p :calendar value is empty?

javascript - HTML 无法解析 'srcset' 属性值,因为它在图像上有未知的描述符 - React - Webpack