2017-02-11 11 views
0

У меня есть модальный, который отображает список контактов. onPress, контакты динамически добавляются в представление. Если контакт уже добавлен, во второй onPress я хотел бы удалить его из представления. Для этого я изменяю состояние/массив, содержащий контакты, используя сплайсинг, но он удаляет все контакты одновременно.React native - удалить объект из массива

Я также пытаюсь обновить состояние значка «Добавить». Если контакт был добавлен, изображение значка Add должно стать активным.

Не знаете, что я делаю неправильно?

Вот Модальные открыл:

enter image description here

Мой код:

import React, {Component} from 'react' 
    import { 
     Text, 
     View, 
     ListView, 
     ScrollView, 
     StyleSheet, 
     Image, 
     TouchableHighlight, 
     TextInput, 
     Modal, 
    } from 'react-native' 


    const friends = new ListView.DataSource({ 
     rowHasChanged: (r1, r2) => r1 !== r2 
    }).cloneWithRows([ 
     { 
      id: 1, 
      firstname: 'name1', 
      surname: 'surname1', 
      image: require('../images/friends/avatar-friend-01.png') 
     }, 
     { 
      id: 2, 
      firstname: 'name2', 
      surname: 'surname2', 
      image: require('../images/friends/avatar-friend-02.png') 
     }, 
     { 
      id: 3, 
      firstname: 'name3', 
      surname: 'surname3', 
      image: require('../images/friends/avatar-friend-03.png') 
     }, 
    ]) 


    class AppView extends Component { 
     state = { 
      isModalVisible: false, 
      contactsPicked: [], 
      friendsState: {}, 
     } 

     setModalVisible = visible => { 
      this.setState({isModalVisible: visible}) 
     } 

     pickContact = (friend) => { 
      if(this.state.contactsPicked.indexOf(friend) < 0){ 
       var tempFriendsState = this.state.friendsState 
       tempFriendsState[friend.id] = true 

       this.setState({ 
        contactsPicked: [ ...this.state.contactsPicked, friend], 
        friendsState: tempFriendsState, 
       }) 
      } 
      else{ 
       let index = this.state.contactsPicked.indexOf(friend) 
       let nextContacts = this.state.contactsPicked 
       nextContacts.splice(index,1) 
       let tempFriendsState = this.state.friendsState 
       tempFriendsState[friend.id] = false 

       this.setState({ 
        contactsPicked: nextContacts, 
        friendsState: tempFriendsState, 
       }) 
      } 
     } 

     removeContact = (friend) => { 
      let index = this.state.contactsPicked.indexOf(friend) 
      let nextContacts = this.state.contactsPicked 
      nextContacts.splice(index,1) 

      this.setState({ 
       contactsPicked: nextContacts, 
      }) 
     } 

     _renderAddFriendTile =() => { 
      return(
       <View style={[styles.step, styles.stepThree]}> 
        <View style={{flex:1}}> 
         <Text style={styles.heading}>Friend tile</Text> 
        </View> 

        {this.state.contactsPicked.length > 0 && (
         <TouchableHighlight onPress={() => {this.removeContact(this.state.contactsPicked)}}> 
          <View> 
           {this.state.contactsPicked.map((contact,index) => (
            <View key={index} style={[styles.row, styles.friendRow]}> 
             <Image source={contact.image} style={styles.friendIcon}></Image> 
             <Text style={styles.name}>{contact.firstname} </Text> 
             <Text style={styles.name}>{contact.surname}</Text> 

             <View style={styles.roundIconContainer}> 
              <View style={styles.roundIcon}> 
               <View style={[styles.removeButton, styles.buttonSmall]}> 
                <Image source={require('../images/button-cross-small.png')} style={styles.crossIconSmall}></Image> 
               </View> 
              </View> 
             </View> 
            </View> 
           ))} 
          </View> 
         </TouchableHighlight> 
        )} 

        <TouchableHighlight style={styles.addFriendButtonContainer} onPress={() => {this.setModalVisible(true)}}> 
         <View style={styles.addFriendButton}> 
          <Text style={styles.addFriendButtonText}>Add friends</Text> 
         </View> 
        </TouchableHighlight> 
       </View> 
      ) 
     } 

     render(){ 
      return (
       <ScrollView style={styles.container}> 
        <Modal 
         animationType={'fade'} 
         transparent={true} 
         visible={this.state.isModalVisible} 
        > 
         <View style={styles.addFriendModalContainer}> 
          <View style={styles.addFriendModal}> 
           <TouchableHighlight onPress={() => {this.setModalVisible(false)}}> 
            <View> 
             <Text>Close</Text> 
            </View> 
           </TouchableHighlight> 
           <ListView 
            dataSource={friends} 
            renderRow={(friend) => { 
             return (
              <FriendRow 
               friend={friend} 
               pickContact={this.pickContact} 
               isSelected={this.state.friendsState[friend.id]} 
              /> 
             ) 
            }} 
           /> 
          </View> 
         </View> 
        </Modal> 

        {this._renderAddFriendTile()} 
       </ScrollView> 
      ) 
     } 
    } 

    class FriendRow extends Component { 
     render(){ 
      return(
       <TouchableHighlight onPress={() => {this.props.pickContact(this.props.friend)}}> 
        <View style={[styles.row, styles.friendRow]}> 
         <Image source={this.props.friend.image} style={styles.friendIcon}></Image> 
         <Text style={styles.name}>{this.props.friend.firstname} </Text> 
         <Text style={styles.name}>{this.props.friend.surname}</Text> 

         <View style={styles.roundIconContainer}> 
          <View style={styles.roundIcon}> 
           <View style={this.props.isSelected ? [styles.buttonActive, styles.buttonSmall]: [styles.modalButtonInactive, styles.buttonSmall]}> 
            <Image source={this.props.isSelected && require('../images/button-tick-small-on.png')} style={styles.buttonTickSmall}></Image> 
           </View> 
          </View> 
         </View> 
        </View> 
       </TouchableHighlight> 
      ) 
     } 
    } 

const styles = StyleSheet.create({ 
    container: { 
     flex: 1, 
     backgroundColor: '#e1e1e1' 
    }, 
    row: { 
     flexDirection: 'row', 
     alignItems: 'center', 
     justifyContent: 'center', 
    }, 
    step: { 
     backgroundColor: '#ffffff', 
     borderRadius: 4, 
     borderLeftWidth: 5, 
     flex: 1, 
     marginLeft: 10, 
     marginRight: 10, 
     marginBottom: 10, 
     paddingLeft: 15, 
     paddingRight: 10, 
     paddingTop: 15, 
     paddingBottom: 20, 
     shadowOffset: { 
      width: 0, 
      height: 2, 
     }, 
     shadowRadius: 2, 
     shadowOpacity: 0.2, 
     shadowColor: '#000000', 
    }, 
    stepThree: { 
     borderLeftColor: '#ffbd18', 
    }, 
    heading: { 
     textAlign: 'center', 
     fontWeight: 'bold', 
     fontSize: 15, 
     color: '#333333', 
    }, 
    addFriendButtonContainer: { 
     marginTop:15, 
     flex:1, 
     alignItems: 'center', 
     justifyContent: 'center', 
     flexDirection: 'row', 
    }, 
    addFriendButton: { 
     backgroundColor: '#ffbd18', 
     width: 270, 
     borderRadius: 4, 
     paddingTop: 15, 
     paddingBottom: 15, 
    }, 
    addFriendButtonText: { 
     color: '#ffffff', 
     fontSize: 18, 
     fontWeight: 'bold', 
     textAlign: 'center', 
    }, 
    pickContainer: { 
     flex:1, 
     flexDirection: 'row', 
     justifyContent: 'space-between', 
     alignItems: 'center', 
     borderRightWidth: 1, 
    }, 
    pickWrapper: { 
     flex: 1, 
     flexDirection: 'row', 
     justifyContent: 'space-around', 
     alignItems: 'center', 
     marginTop: 10, 
    }, 
    buttonBig: { 
     height: 60, 
     width: 60, 
     borderRadius: 30, 
    }, 
    buttonSmall: { 
     height: 20, 
     width: 20, 
     borderRadius: 10, 
    }, 
    buttonActive: { 
     backgroundColor: '#fd6769', 
     alignItems: 'center', 
     justifyContent: 'center', 
    }, 
    buttonInactive: { 
     backgroundColor: '#eeeeee', 
     alignItems: 'center', 
     justifyContent: 'center', 
    }, 
    removeButton:{ 
     backgroundColor: '#cccbcb', 
     alignItems: 'center', 
     justifyContent: 'center', 
    }, 
    modalButtonInactive: { 
     backgroundColor: '#ffffff', 
     borderWidth: 1, 
     borderColor: '#eeeeee', 
    }, 
    buttonTickBig: { 
     width: 34, 
     height: 28, 
    }, 
    buttonTickMinusBig: { 
     width: 18, 
     height: 8, 
    }, 
    buttonTickSmall: { 
     width: 12, 
     height: 10, 
    }, 
    crossIconSmall: { 
     width: 12, 
     height: 10, 
    }, 
    pickText: { 
     color: '#c7c7c7', 
     fontWeight: 'bold', 
    }, 
    addFriendModalContainer: { 
     flex: 1, 
    }, 
    addFriendModal: { 
     flex: 1, 
     backgroundColor: '#ffffff', 
     borderRadius: 4, 
     paddingLeft: 15, 
     paddingRight: 10, 
     paddingTop: 20, 
     paddingBottom: 20, 
     shadowOffset: { 
      width: 0, 
      height: 2, 
     }, 
     shadowRadius: 2, 
     shadowOpacity: 0.2, 
     shadowColor: '#000000', 
     textAlign: 'center', 
    }, 
    nextButtonContainer: { 
     marginBottom: 20, 
    }, 
    nextButton: { 
     textAlign:'right', 
    }, 
    friendRow: { 
     height: 60, 
     borderBottomWidth: 1, 
     borderBottomColor: '#eeeeee', 
     justifyContent: 'flex-start', 
    }, 
    friendIcon: { 
     width: 50, 
     height: 50, 
     marginRight: 25, 
    }, 
    roundIconContainer:{ 
     flex: 1, 
     flexDirection: 'row', 
     justifyContent: 'flex-end', 
     alignItems: 'flex-end', 
    }, 
    roundIcon: { 
     height: 20, 
     width: 20, 
     borderRadius: 10, 
     backgroundColor: '#fd6769', 
     justifyContent: 'center', 
     alignItems: 'center', 
     marginRight: 20, 
    }, 
}) 

export default AppView 

ответ

1

'с помощью сращивания, но он удаляет все контакты сразу. '

Потому что вы используете метод сплайсинга неправильно. Проверьте параметры, которые получает метод. http://www.w3schools.com/jsref/jsref_splice.asp

[... this.state.contactsPicked, this.state.contactsPicked.splice (друг)]

это не работает, как вы ожидали, а также. Он объединяет два массива.

var parts = ['shoulders', 'knees']; 
 
var parts2 = ['shoulders']; 
 
var lyrics = [ ...parts, ...parts2 ]; 
 

 
console.log(lyrics)

Кажется, вы не должны использовать оператор распространения ([... аранжировка, .arr2]), вы можете просто сделать

  1. С ней re создает субмарины каждый раз, когда изменяется видимость модала, и даже если вы изменяете состояние состояния родительского компонента, оно не подлежит обновлению, поэтому вам нужно сохранить внутреннее состояние для ваших подкомпонентов.
  2. Также вы Метод r_renderAddFriendTile тоже работал неправильно. Когда вы внимательно посмотрите на это, вы поймете свою ошибку.
  3. Не забудьте изменить значки с моей тестовой иконкой

class AppView extends Component { 
    constructor(props) { 
     super(props); 
     this.state = { 
     isModalVisible: false, 
     contactsPicked: [], 
     friendsState: {}, 
     } 
    } 

    setModalVisible = visible => { 
     this.setState({isModalVisible: visible}) 
    } 

    pickContact = (friend) => { 
     if(this.state.contactsPicked.indexOf(friend) < 0){ 
      var tempFriendsState = this.state.friendsState 
      tempFriendsState[friend.id] = true 

      this.setState({ 
       contactsPicked: [ ...this.state.contactsPicked, friend], 
       friendsState: tempFriendsState, 
      }) 
     } 
     else{ 
      let index = this.state.contactsPicked.indexOf(friend) 
      let nextContacts = this.state.contactsPicked 
      nextContacts.splice(index,1) 
      let tempFriendsState = this.state.friendsState 
      tempFriendsState[friend.id] = false 

      this.setState({ 
       contactsPicked: nextContacts, 
       friendsState: tempFriendsState, 
      }) 
     } 
    } 

    removeContact = (friend) => { 
     let index = this.state.contactsPicked.indexOf(friend) 
     let nextContacts = this.state.contactsPicked 
     let tempFriendsState = this.state.friendsState 
     tempFriendsState[friend.id] = false 
     nextContacts.splice(index,1) 
     console.log('removeContact'+friend.id); 
     this.setState({ 
      contactsPicked: nextContacts, 
      friendsState: tempFriendsState, 
     }) 
    } 

    _renderAddFriendTile =() => { 
     return(
      <View style={[styles.step, styles.stepThree]}> 
       <View style={{flex:1}}> 
        <Text style={styles.heading}>Friend tile</Text> 
       </View> 

       { (this.state.contactsPicked.length) > 0 ? 
        this.state.contactsPicked.map((contact,index) => (
           <TouchableHighlight onPress={() => {this.removeContact(contact)}}> 
            <View> 
           <View key={index} style={[styles.row, styles.friendRow]}> 
            <Image source={contact.image} style={styles.friendIcon}></Image> 
            <Text style={styles.name}>{contact.firstname} </Text> 
            <Text style={styles.name}>{contact.surname}</Text> 

            <View style={styles.roundIconContainer}> 
             <View style={styles.roundIcon}> 
              <View style={[styles.removeButton, styles.buttonSmall]}> 
               <Image source={require('./images/redtree.jpg')} style={styles.crossIconSmall}></Image> 
              </View> 
             </View> 
            </View> 
           </View> 
           </View> 
          </TouchableHighlight> 
          )) 
          : null 

       } 

       <TouchableHighlight style={styles.addFriendButtonContainer} onPress={() => {this.setModalVisible(true)}}> 
        <View style={styles.addFriendButton}> 
         <Text style={styles.addFriendButtonText}>Add friends</Text> 
        </View> 
       </TouchableHighlight> 
      </View> 
     ) 
    } 

    render(){ 
     return (
      <ScrollView style={styles.container}> 
       <Modal 
        animationType={'fade'} 
        transparent={true} 
        visible={this.state.isModalVisible} 
       > 
        <View style={styles.addFriendModalContainer}> 
         <View style={styles.addFriendModal}> 
          <TouchableHighlight onPress={() => {this.setModalVisible(false)}}> 
           <View> 
            <Text>Close</Text> 
           </View> 
          </TouchableHighlight> 
          <ListView 
           dataSource={friends} 
           renderRow={(friend) => { 
            return (
             <FriendRow 
              friend={friend} 
              pickContact={this.pickContact} 
              isSelected={this.state.friendsState[friend.id]} 
             /> 
            ) 
           }} 
          /> 
         </View> 
        </View> 
       </Modal> 

       {this._renderAddFriendTile()} 
      </ScrollView> 
     ) 
    } 
} 

class FriendRow extends Component { 
    constructor(props) { 
     super(props); 
     this.state = { 
     isSelected:this.props.isSelected, 
     } 
    } 

    componentDidMount(){ 
    console.log('didmount'); 
    } 
    render(){ 
     var imageSource = (this.state.isSelected==true) ? require('./images/tree.jpg') : '' 
     console.log('friend'+!this.props.isSelected) 
     return(
      <TouchableHighlight onPress={() => {this.props.pickContact(this.props.friend);this.setState({isSelected:!this.state.isSelected})}}> 
       <View style={[styles.row, styles.friendRow]}> 
        <Image source={this.props.friend.image} style={styles.friendIcon}></Image> 
        <Text style={styles.name}>{this.props.friend.firstname} </Text> 
        <Text style={styles.name}>{this.props.friend.surname}</Text> 

        <View style={styles.roundIconContainer}> 
         <View style={styles.roundIcon}> 
          <View style={this.state.isSelected ? [styles.buttonActive, styles.buttonSmall]: [styles.modalButtonInactive, styles.buttonSmall]}> 
           <Image source={imageSource} style={styles.buttonTickSmall}></Image> 
          </View> 
         </View> 
        </View> 
       </View> 
      </TouchableHighlight> 
     ) 
    } 
} 
+0

Эй, спасибо за Ваш ответ. Я попробовал ваше решение, но он удаляет все контакты и сохраняет тот, который нужно удалить из добавленных. Что касается второго вопроса, я пытаюсь обновить изображение добавленного значка, был ли добавлен контакт. – John

+0

отредактировал мой ответ –

+0

Отлично, он отлично работает сейчас :) Любые предложения относительно моего второго вопроса? – John

0

Вы можете использовать метод фильтрации, чтобы отфильтровать контакты, если он уже есть в поле зрения.

Чтобы удалить контакты из поля зрения, если уже добавлен:

this.setState({ 
    ...state, 
    contactsPicked: this.state.contactsPicked.filter((contactsPicked,index)=> index != pickedContactsIndex)   
})