javascript - 更换 props 后 componentDidMount 不断重复调用
问题描述
当我做这样的事情时,我遇到了无限循环componentDidMount无限调用自身的问题:
this.props.setRootState({industries: ['hello','world']});
整个代码如下所示:
import React from 'react';
import {Route, Link} from 'react-router-dom';
import FourthView from '../fourthview/fourthview.component';
import {Bootstrap, Grid, Row, Col, Button, Image, Modal, Popover} from 'react-bootstrap';
import Header from '../header/header.component';
import style from './information.style.scss';
import industryApi from '../industries/industry.api';
class InformationFilter extends React.Component {
constructor(props) {
super(props);
this.state = {};
}
componentDidMount() {
industryApi.getAll().then(response => {
if (response.data) {
this.props.setRootState({industries: response.data._embedded.industries});
} else {
console.log(response);
}
});
}
onIndustryChangeOption(event) {
this.props.setRootState({selectedIndustry: event.target.value});
}
onJobChangeOption(event) {
this.props.setRootState({selectedJob: event.target.value});
}
render() {
return (
<div className={"wrapperDiv"}>
<div className={"flexDivCol"}>
<div id="header">
<Header size="small"/>
</div>
<div id="industryFilter">
<h2 className={"center"} style={{marginBottom: '25px'}}>Tietoa Aloista</h2>
<p className={"primaryColor center"}>Valitse opintoala</p>
<div className={"industries dropdownListHolder center"}>
<select id={"dropdownList"} onChange={(e) => this.onIndustryChangeOption(e)}
value={this.props.rootState.selectedIndustry}>
{this.props.rootState.industries.map((industry, i) => <option key={i}
value={industry.id}>{industry.title}</option>)}
</select>
</div>
<p className={"primaryColor center"}>Valitse työtehtävä</p>
<div className={"jobs dropdownListHolder center"}>
<select id={"dropdownList"} onChange={(e) => this.onJobChangeOption(e)}
value={this.props.rootState.selectedJob}>
{this.props.rootState.industries.map((job, i) => <option key={i}
value={job.id}>{job.text}</option>)}
</select>
</div>
</div>
<div id="industryDescription">
<h4>Ravintola- ja cateringala</h4>
<p className={"secondaryColor"}>
Donec facilisis tortor ut augue lacinia, at viverra est semper.
Sed sapien metus, scelerisque nec pharetra id, tempor a tortor. Pellentesque non dignissim
neque. Ut porta viverra est, ut dignissim elit elementum ut. Nunc vel rhoncus nibh, ut
tincidunt turpis. Integer ac enim pellentesque, adipiscing metus id, pharetra odio.
</p>
<p className={"secondaryColor"}>
Donec facilisis tortor ut augue lacinia, at viverra est semper.
Sed sapien metus, scelerisque nec pharetra id, tempor a tortor. Pellentesque non dignissim
neque. Ut porta viverra est, ut dignissim elit elementum ut. Nunc vel rhoncus nibh, ut
tincidunt turpis. Integer ac enim pellentesque, adipiscing metus id, pharetra odio.
</p>
</div>
<div id={"btnFilter"}>
<Link to='/information-job'>
<div onClick={() => this.props.setRootState({globalVariable: 'bar'})}>
<Button className={"primaryBtn"}>Seuraava</Button>
</div>
</Link>
</div>
</div>
</div>
);
}
}
export default InformationFilter;
路由.js
import React from "react";
import {HashRouter, Route, Switch, Redirect, Link} from 'react-router-dom';
import Main from './components/main/main.component';
import SecondView from './components/secondview/secondview.component';
import ThirdView from './components/thirdview/thirdview.component';
import Traineeship from './components/traineeship/traineeships.component';
import InformationFilter from "./components/information/information-filter.component";
import InformationJob from "./components/information/information-job.component";
class AppRoutes extends React.Component {
constructor(props) {
super(props);
this.state = {
selectedIndustry: '',
selectedJob: '',
industries: [],
jobs: [],
}
}
render() {
const InformationFilterPage = () => <InformationFilter rootState={this.state}
setRootState={this.setState.bind(this)}/>;
const InformationJobPage = () => <InformationJob rootState={this.state}
setRootState={this.setState.bind(this)}/>;
const TraineeshipPage = () => <Traineeship rootState={this.state}
setRootState={this.setState.bind(this)}/>;
return (
<HashRouter>
<Switch>
<Route exact path='/' component={Main}/>
<Route path='/secondview' component={SecondView}/>
<Route path='/traineeships' component={TraineeshipPage}/>
<Route path='/information-filter' component={InformationFilterPage}/>
<Route path='/information-job' component={InformationJobPage}/>
<Redirect from='*' to='/'/>
</Switch>
</HashRouter>
);
}
}
export default AppRoutes;
有谁知道这里发生了什么?由于交叉传递值,我将状态保留在此组件中,您可能会说为什么不使用 redux 但问题是我不想用于这个项目,因为它是一个非常小的项目!
解决方案
当您通过 setRootState 在父组件上调用 setState 时,它会设置父组件的状态,实习生会导致其子组件的重新渲染,从而导致子组件重新挂载,调用 componentDidMount 然后再次设置父组件的状态并继续循环。
要解决此问题,您应该调用您的 api 并在父组件本身中设置状态。
你的父组件现在应该有
componentDidMount() {
this.industryApiCall ()
}
industryApiCall = () => {
industryApi.getAll().then(response => {
if (response.data) {
this.props.setState({
industries: response.data._embedded.industries
})
} else {
console.log(response)
}
})
}
您可以将此功能传递给您的孩子,例如
const InformationFilterPage = () => <InformationFilter rootState={this.state}
callApi={this.industryApiCall.bind(this)} />;
并通过调用在您的子组件中使用它
this.props.callApi()
推荐阅读
- sql - SQL:添加外键失败
- numpy - 在TensorFlow中计算张量中所有向量之间的成对欧几里得距离的有效方法
- python - 如何从另一个方法中调用一个方法?
- python - 如何解决 'SpreadsheetNotFound:' 而无需添加 client_email?
- python - 附加到列表后删除 html 源代码中的 \n
- python - Python 将 DXF 文件转换为 PDF 或 PNG 或 JPEG
- java - 查找保存 int number 所需的位数
- c - C中的多个矩阵运算
- java - 在 Gradle Jitpack 项目中构建 Java JNI
- android - 滚动时 FloatActionButton 不隐藏