web-dev-qa-db-fra.com

Pourquoi mon composant React est rendu deux fois?

Je ne sais pas pourquoi mon composant React est rendu deux fois. Je tire donc un numéro de téléphone des paramètres et le sauvegarde pour pouvoir le rechercher dans Firestore. Tout semble bien fonctionner sauf il s'affiche deux fois ... Le premier affiche le numéro de téléphone et zéro point. La deuxième fois, il affiche toutes les données est affiché correctement. Quelqu'un peut-il me guider vers la solution.

class Update extends Component {
constructor(props) {
    super(props);
    const { match } = this.props;
    this.state = {
        phoneNumber: match.params.phoneNumber,
        points: 0,
        error: ''
    }
}

getPoints = () => {
    firebase.auth().onAuthStateChanged((user) => {
        if(user) {
            const docRef = database.collection('users').doc(user.uid).collection('customers').doc(this.state.phoneNumber);
            docRef.get().then((doc) => {
                if (doc.exists) {
                const points = doc.data().points;
                this.setState(() => ({ points }));
                console.log(points);
                } else {
                // doc.data() will be undefined in this case
                console.log("No such document!");
                const error = 'This phone number is not registered yet...'
                this.setState(() => ({ error }));
                }
                }).catch(function(error) {
                console.log("Error getting document:", error);
                });
        } else {
            history.Push('/')
        }
    });
}

componentDidMount() {
    if(this.state.phoneNumber) {
        this.getPoints();
    } else {
        return null;
    }
}

render() {
    return (
        <div>
            <div>
                <p>{this.state.phoneNumber} has {this.state.points} points...</p>
                <p>Would you like to redeem or add points?</p>
            </div>
            <div>
                <button>Redeem Points</button>
                <button>Add Points</button>
            </div>
        </div>
    );
  }
}

export default Update;
7
Raul Sanchez

React restitue le composant avant que getPoints termine l'opération asynchrone.

Ainsi, le premier render montre l'état initial de points qui est 0, puis componentDidMount est appelé et déclenche l'opération asynchrone.
Lorsque l'opération asynchrone est terminée et que l'état a été mis à jour, un autre render est déclenché avec les nouvelles données.

Si vous le souhaitez, vous pouvez montrer à un chargeur ou à un indicateur que les données sont récupérées et ne sont pas encore prêtes à s'afficher avec rendu conditionnel .

Ajoutez simplement une autre clé booléenne comme isFetching, définissez-la sur true lorsque vous appelez le serveur et définissez-la sur false lorsque les données sont reçues.

Votre rendu peut ressembler à ceci:

render() {
  const {isFetching} = this.state;
  return (
    <div>
    {
        isFetching ? <div>Loading...</div> : (
      <div>
        <p>{this.state.phoneNumber} has {this.state.points} points...</p>
            <p>Would you like to redeem or add points?</p>
        </div>
        <div>
                <button>Redeem Points</button>
                <button>Add Points</button>
            </div>
        </div>  
      )
    }
  );
}
8
Sagiv b.g