2016-12-12 2 views
2

이 오류를 제거 할 수 없습니다. 그것은 내 배열에서 하나의 항목을 삭제하고 상태를 업데이트 할 때 일어난 일입니다.경고 : setState (...) : 마운트 된 구성 요소 또는 마운트 된 구성 요소 만 업데이트 할 수 있습니다.

일부 디버깅 후 앱을 새로 고침하고이 화면으로 직접 이동하여 삭제하면 오류가 표시되지 않습니다. 그러나이 화면으로 이동하여 돌아가서이 화면으로 다시 이동하여 삭제하면 오류가 나타납니다. 화면을 10 번로드하면 이와 같은 오류가 발생합니다 (30 개).

내 생각 엔 대시 보드로 돌아 오는 팝업 경로를 firebase 연결이 닫히지 않을 것입니다. 또는 사용중인 네비게이터가 장면을 올바르게 언로드하지 않습니다. 또는 deleteRow() 함수에 문제가 있습니다.

나는 정말로 내가 할 수있는 일을하지 않습니다. 같은 질문은 온통 웹에 있지만 내 시나리오에는 적용되지 않습니다.

constructor(props) { 
    super(props); 
    this.state = { 
     dataSource: new ListView.DataSource({ 
     rowHasChanged: (row1, row2) => row1 !== row2, 
     }), 
    }; 

    const user = firebase.auth().currentUser; 
    if (user != null) { 
     this.itemsRef = this.getRef().child(`Stores/${user.uid}/`); 
    } else { 
     Alert.alert('Error', 'error!'); 
    } 
    this.connectedRef = firebase.database().ref('.info/connected'); 
    } 

    componentWillMount() { 
    this.connectedRef.on('value', this.handleValue); 
    } 

    componentWillReceiveProps() { 
    this.connectedRef.on('value', this.handleValue); 
    } 

    componentWillUnmount() { 
    this.connectedRef.off('value', this.handleValue); 
    } 

    /*eslint-disable */ 
    getRef() { 
    return firebase.database().ref(); 
    } 
    /*eslint-enable */ 

    handleValue = (snap) => { 
    if (snap.val() === true) { 
     this.listenForItems(this.itemsRef); 
    } else { 
     //this.offlineForItems(); 
    } 
    }; 

    listenForItems(itemsRef) { 
    this.itemsRef.on('value', (snap) => { 
     const items = []; 
     snap.forEach((child) => { 
     items.unshift({ 
      title: child.val().title, 
      _key: child.key, 
     }); 
     }); 
     offline2.save('itemsS', items); 
     this.setState({ 
     dataSource: this.state.dataSource.cloneWithRows(items), 
     }); 
    }); 
    } 

    offlineForItems() { 
    offline2.get('itemsS').then((items) => { 
     this.setState({ 
     dataSource: this.state.dataSource.cloneWithRows(items), 
     }); 
    }); 
    } 

    deleteConfirm(data, secId, rowId, rowMap) { 
    Alert.alert(
     'Warning!', 
     'Are you sure?', 
     [ 
      { text: 'OK', onPress:() => this.deleteRow(data, secId, rowId, rowMap) }, 
      { text: 'Cancel', onPress:() => this.deleteCancel(data, secId, rowId, rowMap) }, 
     ] 
    ); 
    } 

    deleteCancel(data, secId, rowId, rowMap) { 
    rowMap[`${secId}${rowId}`].closeRow(); 
    } 

    deleteRow(data, secId, rowId, rowMap) { 
    rowMap[`${secId}${rowId}`].closeRow(); 
    this.itemsRef.child(data._key).remove(); 
    offline2.get('itemsS').then((items) => { 
     const itemsTemp = items; 
     let index = -1; 
     for (let i = 0; i < itemsTemp.length; i += 1) { 
     if (itemsTemp[i]._key === data._key) { 
      index = i; 
     } 
     } 
     if (index > -1) { 
     itemsTemp.splice(index, 1); 
     } 
     // Decrement stores counter 
     offline2.get('storesTotal').then((value) => { 
     const itemsReduce = value - 1; 
     this.setState({ storesValue: itemsReduce }); 
     offline2.save('storesTotal', itemsReduce); 
     }); 

     offline2.save('itemsS', itemsTemp); 
     this.setState({ 
     dataSource: this.state.dataSource.cloneWithRows(itemsTemp), 
     }); 
    }); 
    } 

답변

1

나는 오류 발생으로 이어지는 경우 확실하지 않다 그러나 이것은 당신이 (이벤트 리스너를 제거), 당신은 것이다 바인딩을 해제 할 때문에, 당신은, 바람직하게는 생성자에 이벤트 핸들러를 바인드해야 오류가 동일한 기능을 참조해야합니다.

constructor(props) { 
    super(props); 
    this.state = { 
     dataSource: new ListView.DataSource({ 
     rowHasChanged: (row1, row2) => row1 !== row2, 
     }), 
    }; 

    const user = firebase.auth().currentUser; 
    if (user != null) { 
     this.itemsRef = this.getRef().child(`Stores/${user.uid}/`); 
    } else { 
     Alert.alert('Error', 'error!'); 
    } 
    this.connectedRef = firebase.database().ref('.info/connected'); 
    this.handleValue = this.handleValue.bind(this) // here added 
    } 

희망 사항이 있으면 문제도 해결됩니다.

+0

나는 내 (틀림없이 불확실한) 대답에 놓친 마법의 픽시 먼지라고 생각합니다. 함수 바인딩을 사용하면 이벤트 리스너를 끌 때 작동하지 않는 경우가 많습니다. –

1

모든 이벤트 처리기를 끄는 것이 아닙니다.

'value' 이벤트에 대한 이벤트 처리기는 listenForItems() 함수 안에있는 itemsRef 개체에 만듭니다. 이 이벤트 핸들러는 setState()을 호출합니다. 이 특정 이벤트 핸들러가 꺼지지 않고 있습니다. 즉, 모든 후속 데이터베이스 이벤트가 이전 (마운트 해제 된) 구성 요소에서 setState()을 호출하려고하는 콜백 함수를 호출합니다.

componentWillUnmount() { 
    this.itemsRef.off(); 
    this.connectedRef.off('value', this.handleValue); 
} 
2

문제들이 언급 한 것을,하지만 제공되지 솔루션 :

당신은 thusly 히, componentWillUnmount()에서 이벤트 핸들러의 모든 전원을 끄한다. 잠시 후 외부 도움을 받아 문제가 해결되었습니다. 청취자 만 제거하면됩니다.

componentWillUnmount() { 
    this.itemsRef.off(); // this line 
    this.connectedRef.off('value', this.handleValue); 
    } 
+0

죄송합니다. André - 아마도이 코드 스 니펫을 제 응답에 포함 시켰을 것입니다! 나는 당신 자신의 해결책을 찾은 것을 기쁘게 생각합니다. –