Javascript 为什么我的 React 组件渲染了两次?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/48846289/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why is my React component is rendering twice?
提问by Raul Sanchez
I don't know why my React component is rendering twice. So I am pulling a phone number from params and saving it to state so I can search through Firestore. Everything seems to be working fine except it renders twice... The first one renders the phone number and zero points. The second time it renders all the data is displayed correctly. Can someone guide me to the solution.
我不知道为什么我的 React 组件渲染了两次。所以我从 params 中提取一个电话号码并将其保存到 state 以便我可以在 Firestore 中进行搜索。除了渲染两次之外,一切似乎都工作正常......第一个渲染电话号码和零点。第二次呈现所有数据时都正确显示。有人可以指导我解决问题。
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;
回答by Sagiv b.g
React is rendering the component before getPointsfinishing the asynchronous operation.
React 在getPoints完成异步操作之前渲染组件。
So the first rendershows the initial state for pointswhich is 0, then componentDidMountis called and triggers the async operation.
When the async operation is done and the state been updated, another renderis triggered with the new data.
所以第一个render显示pointsis的初始状态0,然后componentDidMount被调用并触发异步操作。
当异步操作完成并更新状态时,另一个render用新数据触发。
If you want, you can show a loader or an indicator that the data is being fetched and is not ready yet to display with conditional rendering.
如果需要,您可以显示一个加载器或一个指示符,表明数据正在被获取并且还没有准备好通过条件渲染来显示。
Just add another Boolean key like isFetching, set it to true when you call the server and set it to false when the data is received.
只需添加另一个布尔键,例如isFetching,在调用服务器时将其设置为 true,并在接收到数据时将其设置为 false。
Your render can look something like this:
您的渲染可能如下所示:
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>
<button>Redeem Points</button>
<button>Add Points</button>
</div>
</div>
)}
</div>
);
}

