我有一个组件,可以根据之前单击的项目ID获取数据。提取成功,console.log显示了正确的数据,但是数据因this.setState而丢失。我在同一个组件中有componentDidUpdate和componentDidMount,不确定这是否还可以,或者这两个是否使彼此混乱?
这是代码:
const teamAPI = 'http://localhost:8080/api/teams/'
const playerAPI = 'http://localhost:8080/api/playersByTeam/'
const matchAPI = 'http://localhost:8080/api/match/'
class View extends Component {
constructor() {
super();
this.state = {
data: [],
playersData: [],
update: [],
team1: [],
team2: [],
matchData: [],
testTeam: [],
};
}
componentDidUpdate(prevProps) {
if (prevProps.matchId !== this.props.matchId) {
fetch(matchAPI + this.props.matchId)
.then((matchResponse) => matchResponse.json())
.then((matchfindresponse) => {
console.log(matchfindresponse);
this.setState({
matchData:matchfindresponse,
testTeam:matchfindresponse.team1.name,
})
})
}
}
componentDidMount() {
fetch(teamAPI)
.then((Response) => Response.json())
.then((findresponse) => {
console.log(findresponse)
this.setState({
data:findresponse,
team1:findresponse[0].name,
team2:findresponse[1].name,
})
})
fetch(playerAPI + 82)
.then(playerResponse => playerResponse.json())
.then(players => {
console.log(players)
this.setState({
playersData:players
})
})
}
第一个渲染器也会发出以下警告:
Warning: Can only update a mounted or mounting component. This usually means you called setState, replaceState, or forceUpdate on an unmounted component. This is a no-op.
Please check the code for the View component.
ComponentDidMount中的所有内容在渲染中均能正常工作,但componentDidUpdate中的{this.state.matchData}和{this.state.testTeam}为空。
问题可能是ComponentDidMount重新渲染了导致ComponentDidUpdate中的数据丢失的组件,如果这样,我该如何解决?
尝试过ComponentWillReceiveProps这样,但还是没有运气
componentWillReceiveProps(newProps) {
if (newProps.matchId !== this.props.matchId) {
fetch(matchAPI + newProps.matchId)
.then((matchResponse) => matchResponse.json())
.then((matchfindresponse) => {
console.log(matchfindresponse.team1.name);
console.log(this.props.matchId + ' ' + newProps.matchId);
this.setState({
matchData:matchfindresponse.team1.name,
})
})
}
}
最佳答案
在您的componentDidMount上,您应该使用Promise.all。这实际上不是您的问题,但确实更有意义。
componentDidMount() {
const promises = [
fetch(teamAPI).then(resp => resp.json()),
fetch(playerAPI + 82).then(resp => resp.json())
];
Promise.all(promises).then(([teamData, playerData]) => {
// you can use this.setState once here
});
}
看起来您的componentDidUpdate应该是与componentDidUpdate结合使用的getDerivedStateFromProps(这是16.3的新功能,因此,如果您使用的是旧版本,请使用已贬值的componentWillReceiveProps)。请参阅https://github.com/reactjs/rfcs/issues/26。还要注意,现在componentDidUpdate从getDerivedStateFromProps接收了第三个参数。有关更多详细信息,请参见https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html。
编辑:只是添加更多详细信息。
您的状态对象应该只包含其他关键字,例如matchIdChanged。
然后
// in your state in your constructor add matchId and matchIdChanged then
static getDerivedStateFromProps(nextProps, prevState) {
if (nextProps.matchId !== prevState.matchId) {
return { matchIdChanged: true, matchId: nextProps.matchId }
}
return null;
}
componentDidUpdate() {
if (this.state.matchIdChanged) {
fetch(matchAPI + this.props.matchId)
.then((matchResponse) => matchResponse.json())
.then((matchfindresponse) => {
console.log(matchfindresponse);
this.setState({
matchData:matchfindresponse,
testTeam:matchfindresponse.team1.name,
matchIdChanged: false // add this
})
})
}
}