我得到这个警告在反应:
index.js:1 Warning: Cannot update a component (`ConnectFunction`)
while rendering a different component (`Register`). To locate the
bad setState() call inside `Register`
我去了堆栈跟踪中指出的位置,并删除了所有设置状态,但警告仍然存在。这可能发生在redux调度?
我的代码:
register.js
class Register extends Component {
render() {
if( this.props.registerStatus === SUCCESS) {
// Reset register status to allow return to register page
this.props.dispatch( resetRegisterStatus()) # THIS IS THE LINE THAT CAUSES THE ERROR ACCORDING TO THE STACK TRACE
return <Redirect push to = {HOME}/>
}
return (
<div style = {{paddingTop: "180px", background: 'radial-gradient(circle, rgba(106,103,103,1) 0%, rgba(36,36,36,1) 100%)', height: "100vh"}}>
<RegistrationForm/>
</div>
);
}
}
function mapStateToProps( state ) {
return {
registerStatus: state.userReducer.registerStatus
}
}
export default connect ( mapStateToProps ) ( Register );
函数,该函数触发了由register.js调用的registerForm组件中的警告
handleSubmit = async () => {
if( this.isValidForm() ) {
const details = {
"username": this.state.username,
"password": this.state.password,
"email": this.state.email,
"clearance": this.state.clearance
}
await this.props.dispatch( register(details) )
if( this.props.registerStatus !== SUCCESS && this.mounted ) {
this.setState( {errorMsg: this.props.registerError})
this.handleShowError()
}
}
else {
if( this.mounted ) {
this.setState( {errorMsg: "Error - registration credentials are invalid!"} )
this.handleShowError()
}
}
}
堆栈跟踪:
我认为这很重要。
@Red-Baron在这篇文章中指出:
@machineghost:我认为你误解了这条信息警告的内容。
将更新父节点状态的回调传递给子节点并没有什么错。这一直都很好。
问题是当一个组件在另一个组件中排队更新时,而第一个组件正在呈现。
换句话说,不要这样做:
function SomeChildComponent(props) {
props.updateSomething();
return <div />
}
但这是可以的:
function SomeChildComponent(props) {
// or make a callback click handler and call it in there
return <button onClick={props.updateSomething}>Click Me</button>
}
而且,正如Dan多次指出的那样,在渲染时在同一个组件中排队更新也很好:
function SomeChildComponent(props) {
const [number, setNumber] = useState(0);
if(props.someValue > 10 && number < 5) {
// queue an update while rendering, equivalent to getDerivedStateFromProps
setNumber(42);
}
return <div>{number}</div>
}
我通过将分配从寄存器组件渲染方法移除到componentwillunmount方法来修复这个问题。这是因为我希望这个逻辑在重定向到登录页面之前发生。一般来说,最好的做法是把所有的逻辑都放在渲染方法之外,所以我的代码之前写得很糟糕。希望这能在将来对其他人有所帮助:)
我重构的寄存器组件:
class Register extends Component {
componentWillUnmount() {
// Reset register status to allow return to register page
if ( this.props.registerStatus !== "" ) this.props.dispatch( resetRegisterStatus() )
}
render() {
if( this.props.registerStatus === SUCCESS ) {
return <Redirect push to = {LOGIN}/>
}
return (
<div style = {{paddingTop: "180px", background: 'radial-gradient(circle, rgba(106,103,103,1) 0%, rgba(36,36,36,1) 100%)', height: "100vh"}}>
<RegistrationForm/>
</div>
);
}
}
我认为这很重要。
@Red-Baron在这篇文章中指出:
@machineghost:我认为你误解了这条信息警告的内容。
将更新父节点状态的回调传递给子节点并没有什么错。这一直都很好。
问题是当一个组件在另一个组件中排队更新时,而第一个组件正在呈现。
换句话说,不要这样做:
function SomeChildComponent(props) {
props.updateSomething();
return <div />
}
但这是可以的:
function SomeChildComponent(props) {
// or make a callback click handler and call it in there
return <button onClick={props.updateSomething}>Click Me</button>
}
而且,正如Dan多次指出的那样,在渲染时在同一个组件中排队更新也很好:
function SomeChildComponent(props) {
const [number, setNumber] = useState(0);
if(props.someValue > 10 && number < 5) {
// queue an update while rendering, equivalent to getDerivedStateFromProps
setNumber(42);
}
return <div>{number}</div>
}
如果useEffect不能在您的情况下使用或如果错误不是由于Redux
我使用setTimeout将两个useState变量中的一个重定向到回调队列。
我有一个父组件和一个子组件,每个组件中都有useState变量。解决方案是使用setTimeout来包装useState变量:
setTimeout(() => SetFilterData(data), 0);
在下面的例子
父组件
import ExpenseFilter from '../ExpensesFilter'
function ExpensesView(props) {
const [filterData, SetFilterData] = useState('')
const GetFilterData = (data) => {
// SetFilterData(data);
//*****WRAP useState VARIABLE INSIDE setTimeout WITH 0 TIME AS BELOW.*****
setTimeout(() => SetFilterData(data), 0);
}
const filteredArray = props.expense.filter(expenseFiltered =>
expenseFiltered.dateSpent.getFullYear().toString() === filterData);
return (
<Window>
<div>
<ExpenseFilter FilterYear = {GetFilterData}></ExpenseFilter>
子组件
const ExpensesFilter = (props) => {
const [filterYear, SetFilterYear] = useState('2022')
const FilterYearListener = (event) => {
event.preventDefault()
SetFilterYear(event.target.value)
}
props.FilterYear(filterYear)
return (