Solucionado (ver solução)
Solucionado
(ver solução)
2
respostas

Erro quando adiciono novo comentario

Olá

Estou com problemas na hora de inserir um novo comentário. No primeiro post assim que adiciono uma vez já aparece um warn de key duplicada. Se eu inserir no segundo post eu consigo inserir a primeira vez, porém na segunda já começa a aparecer key duplicada também.

Segue abaixo o código do post.js

import React, { Component } from 'react';
import {
  StyleSheet,
  Text,
  View,
  Image,
  Dimensions,
  FlatList,
  TouchableOpacity,
  TextInput
} from 'react-native';

const width = Dimensions.get('screen').width;

const icone = require('../../resources/img/send.png');

export default class Post extends Component {

  constructor(props) {
    super(props)

    this.state = { foto: this.props.foto, comentario: '' }
  }

  like() {
    const { foto } = this.state;

    let novaLista = [];
    if(!foto.likeada) {
        novaLista = [
          ...foto.likers,
          { login: 'meuUsuario'}
        ]
    } else {
      novaLista = foto.likers.filter( liker => {
        return liker.login !== 'meuUsuario'
      })
    }

    const fotoAtualizada = { ...this.state.foto, 
      likeada: !this.state.foto.likeada,
      likers: novaLista}
    this.setState( {foto: fotoAtualizada})
  }

  exibeLikes(likers) {
    if (likers <= 0) return;

      return (
        <Text style={styles.likes}>
          {likers.length} {likers.length > 1 ? 'curtidas' : 'curtida'}
        </Text>
      );
  }

  exibeLegenda(foto) {
    if (foto === '') return;

    return(
      <View style={styles.comentario}>
        <Text style={styles.tituloComentario}>{foto.loginUsuario}</Text>
        <Text>{foto.comentario}</Text>
      </View>
    );
  }

  carregaIcone(likeada) {
    return likeada ? require('../../resources/img/s2-checked.png') : 
    require('../../resources/img/s2.png')
  }

  adicionaComentario() {

    const novaLista = [ ...this.state.foto.comentarios, {
      id: this.state.comentario,
      login: 'meuUsuario',
      texto: this.state.comentario
    }];

    const fotoAtualizada = {
      ...this.state.foto,
      comentarios: novaLista
    }

     this.setState({ foto: fotoAtualizada });

     this.inputComentario.clear();

  }

  render() {

    const { foto } = this.state;

    return (
      <View>
        <View style={styles.cabecalho}>
          <Image source={{uri: foto.urlPerfil}}
              style={styles.fotoDePerfil}/>
          <Text>{foto.loginUsuario}</Text>
        </View>
        <Image source={{uri: foto.urlFoto}}
            style={styles.foto}/>

        <View style={styles.rodape}>
        <TouchableOpacity
        onPress={ this.like.bind(this) }>
          <Image style={styles.botaoDeLike}
            source={ this.carregaIcone(foto.likeada) }/>
        </TouchableOpacity>
        </View>
        {this.exibeLikes(foto.likers)}
        {this.exibeLegenda(foto)}

        {foto.comentarios.map( comentario => 
            <View key={foto.id} style={styles.comentario}>
              <Text style={styles.tituloComentario}>{comentario.login}</Text>
              <Text >{comentario.texto}</Text>
            </View>
          )
        }

        <View style={ styles.comentario }>
          <TextInput style={styles.input}
            placeholder='Adicione um comentário...'
            ref={ input => this.inputComentario = input }
            onChangeText={ (texto) => this.setState({ comentario: texto })}/>
          <TouchableOpacity
            onPress={ this.adicionaComentario.bind(this) }>
            <Image style={styles.icone} source={icone}/>
          </TouchableOpacity>
        </View>

      </View>
    );
  }
}

const styles = StyleSheet.create({
  cabecalho: {
    margin: 10,
    flexDirection: 'row',
    alignItems: 'center'
  },
  fotoDePerfil: {
    marginRight: 10,
    borderRadius: 20,
    width: 40,
    height: 40
  },
  foto: {
    width: width,
    height: width
  },
  botaoDeLike: {
    height: 40,
    width: 40,
  },
  rodape: {
    margin: 10,
  },
  comentario: {
    flexDirection: 'row',
    alignItems: 'center'
  },
  tituloComentario: {
      fontWeight: 'bold',
      marginRight: 5,
  },
  input:{
    flex: 1,
    height: 40,
    borderBottomWidth: 1,
    borderBottomColor: '#ddd'
  },
  icone:{
    width: 30,
    height: 30
  }
});
2 respostas
solução!

Fala Vitor, tudo bem ?

Tente usar o id do próprio comentário como key ao renderizar os elementos na lista de comentários, ao invés de utilizar o id da foto. Assim cada elemento da lista renderizado terá um id único. Se usar o id da foto, dois comentários diferentes em uma mesma foto teriam mesmo id, fazendo o RN soltar o warning sobre as chaves.

Exemplo:

...
{foto.comentarios.map(comentario => (
    <View style={styles.comentario} key={comentario.id}>
        <Text style={styles.tituloComentario}>meuUsuario</Text>
        <Text>{comentario.texto}</Text>
    </View>
))}
...

Como outra dica, tente atualizar o estado da informação que recebe o texto do TextInput após a inserção do mesmo, bem como a verificação de valor no início da função, pra evitar entradas repetidas a um simples toque por engano do usuario.

...
  adicionaComentario() {
    if(this.state.comentario === '')
      return;

    const novaLista = [...this.state.foto.comentarios, {
      id: this.state.comentario,
      login: 'meuUsuario',
      texto: this.state.comentario
    }];

    const fotoAtualizada = {...this.state.foto,
      comentarios: novaLista
    };

    // atualizando estado da informação do comentário e limpando o campo de texto aqui
    this.setState({foto: fotoAtualizada, comentario: ''});
    this.inputComentario.clear();
  }

Espero ter ajudado. Abraço!

Fala Rafael,

Problema resolvido, obrigado pela ajuda!