在App.js中,我将setURL(page){ ... }
作为对HealthForm的支持。
在HealthForm中,我有一个输入字段,该字段接受URL的String和一个按钮,该按钮发起对后端服务器的提取调用,并且一些数据会在promise对象中接收回来。我还在promiseStatus函数内调用that.props.changeUrl(that.state.someURL);
,因为这是我唯一可以放置它而不收到以下警告的地方:
Warning: Can't call setState (or forceUpdate) on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.
但是,每次调用that.props.changeUrl(that.state.someURL)
时,页面都会重新呈现。基本上-输入字段和由于fetch调用而呈现的其他功能-全部重置。不过App.js中的url状态会更新。
当我调用父道具时,为什么整个页面都会重新渲染?
如果仅删除行that.props.changeUrl(that.state.someURL)
,则应用不会重新渲染,但是当然它不会更改应用状态
我需要不重新渲染页面,因为重要信息是在fetch调用之后渲染的,由于重新渲染会重置该路由,因此无法看到。
App.js
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
url: '',
};
this.setURL = this.setURL.bind(this);
}
setURL(link) {
this.setState({
url: link
});
}
render(){
return(
<MuiThemeProvider>
<Router>
<div className="App">
<Route path="/" component={Header}></Route>
<Route path="/health" component={()=>(
<HealthForm changeUrl={this.setURL}/>)}></Route>
<Route path="/path1" component={wForm}></Route>
<Route path="/path2" component={xForm}></Route>
<Route path="/path3" component={yForm}></Route>
<Route path="/path4" component={zForm}></Route>
</div>
</Router>
</MuiThemeProvider>
);
}
}
HealthForm.js
class HealthForm extends React.Component {
constructor(props) {
super(props);
this.state = {
exampleURL: '',
exampleURLError: '',
status: '',
showStatus: false
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
validate = () => {
//…checks for input errors
}
handleChange(event) {
this.setState({
[event.target.name]: event.target.value
});
}
handleSubmit(event) {
event.preventDefault();
const err = this.validate();
let that = this;
if (!err) {
this.setState({
exampleURLError: ''
});
console.log(this.state);
var data = this.state.exampleURL
fetch('htpp://...', {
method: 'POST',
body: JSON.stringify(data)
})
.then((result) => {
var promiseStatus = result.text();
promiseStatus.then(function (value) {
that.setState({
status: value,
showStatus: true
});
that.props.changeUrl(that.state.jarvisURL);
});
}).catch((error) => {
console.log(error);
});
}
}
render() {
return (
<form>
<TextField
...
/>
<br/>
<Button variant="contained" size="small" color="primary" onClick={e => this.handleSubmit(e)} >
Check
</Button>
<br /> <br />
...
</form>
);
}
}
export default HealthForm;
答案 0 :(得分:1)
之所以发生这种情况,是因为您在setState()
组件上调用App
,导致其重新呈现,包括重新创建了所有已设置的路由。我不确定您使用的是哪个路由器,但似乎它正在重新创建路由下的组件,可能是通过再次调用作为道具传递的component
函数并获取{ {1}}组件。
我假设应用程序中的所有组件都要求将您存储在HealthForm
中的状态,这就是为什么要将其放置在其中?如果不是,请将其向下移动到App
组件中,但是如果是这样,该是时候考虑将状态存储到组件的外部了,例如在诸如Redux之类的状态容器中或其他Flux风格的容器中。
编辑:我认为问题的根源在这里:
HealthForm
事实上,函数是作为<Route path="/health" component={()=>(<HealthForm changeUrl={this.setURL}/>)}></Route>
属性传递的,每次都会导致组件的新实例。我可以理解为什么您需要这样做,以将对component
的引用传递到setURL()
中-通过从组件中提取状态也可以避免这种情况。