React类组件state更新后自动回退至默认值问题排查
问题原因
状态自动回退是两处代码逻辑错误导致的,和React生命周期、setState机制本身无关:
componentDidMount的接口回调逻辑错误:判断容器已部署的if(data[0])分支执行完setState({deployed:0})后,没有阻断后续代码执行,后面紧跟了无条件执行的setState({deployed:1}),所以不管接口返回是不是已部署,最后都会把状态强制改回1,这就是更新后几毫秒回退的直接原因。onClickKill方法逻辑错误:停止容器的fetch请求刚发起、还没等后端返回成功结果,就同步执行了setState({deployed:1}),哪怕后端删除接口报错,状态也会被提前改成未部署。
修复方案
- 给
componentDidMount里的未部署状态更新加上else分支,只有确认容器未部署时才把deployed设为1,杜绝无条件覆盖状态的问题 - 把
onClickKill里的状态更新移到删除接口请求成功的回调内,只有后端确认删除成功后再更新状态 - 顺手修复
killButton的参数接收问题:方法接收的是url字符串,不需要按props对象解析
修复后完整代码
import React, { Component } from 'react' import { Button } from 'antd'; export class Deploy extends Component { state = { deployed: 1, // 0 已部署, 1 未部署, 2 后端服务异常 url: "" }; componentDidMount() { const url = "http://ip:3001/check?run_id="+this.props.modelVersion.run_id; fetch(url) .then((response) => response.json()) .then((data) => { console.log("data"+ data); if(data[0]) { // 已部署 this.setState({ deployed: 0, url: data[1] }); } else { // 未部署 this.setState({ deployed: 1, url: data[1] }); } }) .catch(err => { // 服务不可用 this.setState({ deployed: 2 }); }); } onClickDeploy = () => { const url = "http://ip:3001/deploy?run_id="+this.props.modelVersion.run_id; fetch(url) .then((response) => { if (!response.ok) { throw Error("Some issue with Fastapi server. Check logs for more information."); } return response.json()}) .then((data) => { alert(data) this.setState({ deployed: 0, url: data }); }) .catch(err => { alert(err.message); this.setState({ deployed: 2 }); }); } onClickKill = () => { const url = "http://ip:3001/delete?run_id="+this.props.modelVersion.run_id; fetch(url) .then((response) => { if (!response.ok) { throw Error("Some issue with Fastapi server. Check logs for more information."); } return response.json()}) .then((data) => { alert(data) // 只有删除成功才更新为未部署状态 this.setState({ deployed: 1 }) }) .catch(err => { alert(err.message); this.setState({ deployed: 2 }); }); } deployButton() { return( <Button type='primary' onClick={this.onClickDeploy}> Deploy </Button> ) } killButton(url) { return( <> <Button type='primary' onClick={this.onClickKill}> Kill </Button> <p>url: {url}</p> </> ) } disableButton() { return( <Button type='primary' disabled={true}> BackEnd is Down </Button> ) } render() { const {deployed, url} = this.state; console.log(deployed); console.log(url); if(deployed==0) { return this.killButton(url); } if(deployed==1) { return this.deployButton(); } return this.disableButton(); } }
内容的提问来源于stack exchange,提问作者NoobCoder
相关产品推荐
相关产品推荐

