簡體   English   中英

setState 也會改變屏幕道具

[英]setState also changes screen props

我有一個大問題。 我有一個從另一個屏幕接收一些道具的屏幕,我通過<TicketDiaryHour {...this.props} />將這些道具傳遞到那個屏幕中的組件中。 我在componentDidMount()方法中將組件中的這些道具設置為我的狀態。

在該組件 (TicketDiaryHour) 中,我也有 flatlist。 我的問題是我更改了 flatlist 中的數據(通過 setState)並且道具也在更改......我不知道為什么會發生這種情況。

我的 componentDidUpdate() 返回 prevProps == this.props 和 prevState == this.state。 我不知道為什么...

看:

Prev props: {"navigation":{"state":{"params":{"props":{"id":"418103","headingText":"Klavir","roomText":"Mala dvorana","student":"Ives Berlovčnik","apsent":"1/1","startTime":"07:00","endTime":"07:30","finished":"0","listOfStudents":[{"nameLastname":"Ives Berlovčnik","id":"43275","checked":false,"o":true,"n":false}],"minutes":"30","notes":"","lesson":""}}}

This props: {"navigation":{"state":{"params":{"props":{"id":"418103","headingText":"Klavir","roomText":"Mala dvorana","student":"Ives Berlovčnik","apsent":"1/1","startTime":"07:00","endTime":"07:30","finished":"0","listOfStudents":[{"nameLastname":"Ives Berlovčnik","id":"43275","checked":false,"o":true,"n":false}],"minutes":"30","notes":"","lesson":""}}}

組件代碼:Flatlist;

<FlatList
                                    ref={(list) => this.myList = list}
                                    style={[styles.flatList,{height: this.state.height}]}
                                    data={this.state.data}
                                    scrollEnabled = {this.state.showList ? true : false}

                                    contentContainerStyle={{ padding: 15 }}
                                    renderItem={({ item }) => (

                                          <View style={styles.listItemStyle}>
                                            <View style={{flexDirection: 'row', marginBottom: 7, }}>

                                                {
                                                    item.checked && 
                                                    <TouchableOpacity
                                                        onPress={this.changeCheckedToFalse.bind(this,item)}>
                                                        <View style={styles.checked} /> 
                                                    </TouchableOpacity> || 
                                                    <TouchableOpacity
                                                        onPress={this.changeCheckedToTrue.bind(this,item)}>
                                                        <View style={styles.unchecked} />
                                                    </TouchableOpacity>
                                                }


                                                <Text style={{color: '#000', opacity: 0.6}}>{item.nameLastname}</Text>
                                                {
                                                    item.checked &&
                                                    <View style={{position: 'absolute', right: 0 }}>
                                                        <View style={{flexDirection: 'row'}} >
                                                        {
                                                            item.o &&
                                                            <TouchableOpacity 
                                                                style={[styles.touchable1Ch,styles.iconStyle1]} 
                                                                onPress={this.changeSelectionO.bind(this,item)}>

                                                                <Text style={{color: '#fff', fontSize: 18, alignSelf: 'center' }}>O</Text>
                                                            </TouchableOpacity> ||
                                                            <TouchableOpacity 
                                                                style={[styles.touchable1,styles.iconStyle1]} 
                                                                onPress={this.changeSelectionO.bind(this,item)}>

                                                                <Text style={{color: '#fff', fontSize: 15, alignSelf: 'center' }}>O</Text>
                                                            </TouchableOpacity>
                                                        }
                                                        {
                                                            item.n &&
                                                            <TouchableOpacity 
                                                                style={[styles.touchable2Ch,styles.iconStyle1]} 
                                                                onPress={this.changeSelectionN.bind(this,item)}>
                                                                <Text style={{color: '#fff', fontSize: 18, alignSelf: 'center' }}>N</Text>
                                                            </TouchableOpacity> ||
                                                            <TouchableOpacity 
                                                                style={[styles.touchable2,styles.iconStyle1]}
                                                                onPress={this.changeSelectionN.bind(this,item)}>
                                                                <Text style={{color: '#fff', fontSize: 15, alignSelf: 'center' }}>N</Text>
                                                            </TouchableOpacity>
                                                        }




                                                        </View>
                                                    </View>
                                                }
                                            </View>
                                            {
                                                this.props.navigation.state.params.props.listOfStudents !== undefined && this.props.navigation.state.params.props.listOfStudents.length >= 2 ?
                                                <View style={styles.line} /> : <Text></Text>
                                            }

                                          </View>



                                    )}
                                    keyExtractor={item => item.id}
                                />

我如何在該組件中加載數據:

componentDidMount() {



        this.setState({
            data: this.props.navigation.state.params.props.listOfStudents,
            textOpombe: this.props.navigation.state.params.props.notes,
            textVsebinaUre: this.props.navigation.state.params.props.lesson,
            finished: this.props.navigation.state.params.props.finished,
            absent: parseInt(this.props.navigation.state.params.props.apsent.substring(0,1)),
        });
}

我如何更改 flatlist 中的數據;

changeCheckedToFalse = (item) => {
      console.log('Item');
        var arr = this.state.data;

        var indexOfItem = arr.indexOf(item);
        arr[indexOfItem].checked = false;
        var abs = this.state.absent;
        abs -= 1;
        this.setState({
            data: arr,
            //scrollingParent: false,
            //scrollingChild: true,
            absent: abs,
        });

          console.log('State after changing: ' + JSON.stringify(this.state.data));
    }

和最終代碼; 更改 flatlist 項時,會觸發此方法

componentDidUpdate(prevProps, prevState) {
          console.log('Prev props: ' + JSON.stringify(prevProps));
          console.log('This props: ' + JSON.stringify(this.props));

          console.log('Prev state: ' + JSON.stringify(prevState));
}

在我看來,您實際上正在改變this.state.data / this.props.navigation.state.params.props.listOfStudents - 因為它們是相同的。

我想你包括這一行: var arr = this.state.data; 試圖復制this.state.data的值,但恐怕它不適用於引用類型(例如數組)。 arr實際上指向完全相同的數組this.state.datathis.state.data點完全相同的數組this.props...listOfStudents

所以當你改變一個值時: arr[indexOfItem].checked = false; 你實際上是在改變道具。

React 非常重要的規則之一是“不要改變任何東西”,那么您將如何解決這個問題?

最簡單的方法是在更改數組之前正確復制它:

使用擴展運算符
var arr = [...this.state.data];

或者Array.prototype.slice方法
var arr = this.state.data.slice()

編輯:雖然上述是正確的,並且如果您有一組原語可以解決您的問題,但實際上您有一組對象引用,這些問題與上述完全相同。

復制數組不會復制里面的對象,只是對這些對象的引用,所以你有同樣的問題。 嘗試對數組進行深拷貝:

var arr = this.state.data.map(x => ({...x}));

或者只復制您正在更改的對象:

var arr = [...this.state.data];
var indexOfItem = arr.indexOf(item);

arr[indexOfItem] = {...item, checked: false};

為什么說道具變了? 您在問題中指定的 prevProps 和 this.props 是相同的。 當您使用 setState 方法時,組件被更新,觸發 componentDidUpdate 生命周期方法運行。 這並不意味着你的道具改變了。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM