私のReactコンポーネントが2回レンダリングされている理由がわかりません。だから私はFirestoreで検索できるように、paramsから電話番号を引き出して状態に保存しています。 1回目は電話番号とゼロポイントをレンダリングし、2回目はすべてのデータが正しく表示されます。
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;
Reactは、getPoints
が非同期操作を完了する前にコンポーネントをレンダリングしています。
したがって、最初のrender
はpoints
の初期状態を示し、これは0
、その後componentDidMount
が呼び出され、非同期操作をトリガーします。
非同期操作が完了し、状態が更新されると、新しいデータで別のrender
がトリガーされます。
必要に応じて、ローダーまたはデータがフェッチされており、まだ表示する準備ができていないことを示すインジケータを 条件付きレンダリング で表示できます。
isFetching
などの別のブールキーを追加し、サーバーを呼び出すときにtrueに設定し、データを受信するときにfalseに設定します。
レンダーは次のようになります。
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>
)
}
);
}