簡體   English   中英

React-Native如何為每個項目設置不同的狀態

[英]React-Native How to have a different state for each item

我有一個組件,當我單擊圖標時,我會執行一個修改狀態的函數,然后可以檢查狀態並修改圖標。 在這種情況下,我正在映射數據,它呈現了幾個項目。 但是,當我單擊一個圖標時,組件的所有圖標也會更改。

這是組件的代碼

export default class DiscoveryComponent extends Component {

    constructor(props) {
        super(props)
        this.state = {
            starSelected: false
        };
    }

    static propTypes = {
        discoveries: PropTypes.array.isRequired
    };

    onPressStar() {
        this.setState({ starSelected: !this.state.starSelected })
    }

    render() {
        return (
            this.props.discoveries.map((discovery, index) => {
                return (
                    <Card key={index} style={{flex: 0}}>
                        <CardItem>
                            <TouchableOpacity style={[styles.star]}>
                                <Icon style={[styles.iconStar]} name={(this.state.starSelected == true)?'star':'star-outline'} onPress={this.onPressStar.bind(this)}/>
                            </TouchableOpacity>
                        </CardItem>
                    </Card>
                )
            })
        );
    }
}

這是使用該組件的屏幕代碼

export default class DiscoveryItem extends Component {

    constructor(props) {
      super(props);

      this.state = {
        discoveries: [],
        loading: true
      };
    }

    componentDidMount() {
      firebase.database().ref("discoveries/").on('value', (snapshot) => {
        let data = snapshot.val();
        let discoveries = Object.values(data);
        this.setState({discoveries: discoveries, loading: false});
      });
    }

    render() {
        return (
          <Container>
            <Content> 
              <DiscoveryComponent discoveries={this.state.discoveries} />
            </Content>
          </Container>
        )
    }
}

您的輸入是正確的,但是缺少每個項目的INDEX this.onPressStar()方法內部,檢查項目的索引是否為currentItem。 另外,別忘了設置項目ID = onpress。

我希望這使您知道如何處理。

您必須將星星變成一個數組並為其索引:

更改您的構造函數:

 constructor(props) {
        super(props)
        this.state = {
            starSelected: []
        };
    }

將您的onPressStar函數更改為:

onPressStar(index) {
    this.setState({ starSelected[index]: !this.state.starSelected })
}

和您的圖標

<Icon style={[styles.iconStar]} name={(this.state.starSelected[index] == true)?'star':'star-outline'} onPress={()=>this.onPressStar(index)}/>

好吧,問題在於您只有一個“ starSelected”值,您的地圖函數中的所有渲染項都在監聽。 因此,當一個人成為事實時,所有人都成為事實。

您可能應該在頂層組件中保持選定狀態,並向下傳遞發現,是否選擇了發現以及如何將被選擇作為道具切換為每個發現的渲染功能。

export default class DiscoveryItem extends Component {

    constructor(props) {
      super(props);

      this.state = {
        discoveries: [],
        selectedDiscoveries: [] // NEW
        loading: true
      };
    }

    toggleDiscovery = (discoveryId) => {
      this.setState(prevState => {
        const {selectedDiscoveries} = prevstate
        const discoveryIndex = selectedDiscoveries.findIndex(id => id === discoveryId)
        if (discoveryIndex === -1) { //not found
          selectedDiscoveries.push(discoveryId) // add id to selected list
        } else {
          selectedDiscoveries.splice(discoveryIndex, 1) // remove from selected list
        }
        return {selectedDiscoveries}
      }
    }

    componentDidMount() {
      firebase.database().ref("discoveries/").on('value', (snapshot) => {
        let data = snapshot.val();
        let discoveries = Object.values(data);
        this.setState({discoveries: discoveries, loading: false});
      });
    }

    render() {
        return (
          <Container>
            <Content> 
              {
                this.state.discoveries.map(d => {
                  return <DiscoveryComponent key={d.id} discovery={d} selected={selectedDiscoveries.includes(d.id)} toggleSelected={this.toggleDiscovery} />
              //<DiscoveryComponent discoveries={this.state.discoveries} />
            </Content>
          </Container>
        )
    }
}

然后,您可以使用DiscoveryComponent為每個對象進行渲染,現在您將狀態保持在頂層,並向下傳遞發現(如果已選擇),並將切換功能作為道具。

另外,我認為您也許可以從firebase中獲取snapshot.docs() (我不確定,因為我使用firestore),然后可以確保值中包含文檔ID。 如果snapshot.val()不包含ID,那么您應該弄清楚如何包括該ID,以確保您將ID用作地圖函數以及selectedDiscoveries數組中的兩個鍵。

希望能有所幫助

現在可以了,謝謝。 我在Malik和Rodrigo的回答之間混在一起。

這是我組件的代碼

export default class DiscoveryComponent extends Component {

    constructor(props) {
        super(props)
        this.state = {
            tabStarSelected: []
        };
    }

    static propTypes = {
        discoveries: PropTypes.array.isRequired
    };

    onPressStar(index) {
        let tab = this.state.tabStarSelected;
        if (tabStar.includes(index)) { 
            tabStar.splice( tabStar.indexOf(index), 1 );
        }
        else {
            tabStar.push(index); 
        }
        this.setState({ tabStarSelected: tab })
    }

    render() {
        return (
            this.props.discoveries.map((discovery, index) => {
                return (
                    <Card key={index} style={{flex: 0}}>
                        <CardItem>
                            <Left>
                                <Body>
                                    <Text note>{discovery.category}</Text>
                                    <Text style={[styles.title]}>{discovery.title}</Text>
                                </Body>
                            </Left>
                            <TouchableOpacity style={[styles.star]}>
                                <Icon style={[styles.iconStar]} name={(this.state.tabStarSelected[index] == index)?'star':'star-outline'} onPress={()=>this.onPressStar(index)}/>
                            </TouchableOpacity>
                        </CardItem>
                    </Card>
                )
            })
        );
    }
}

暫無
暫無

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

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