Javascript 呈现其他组件警告时无法更新组件

Javascript 呈现其他组件警告时无法更新组件,javascript,reactjs,redux,Javascript,Reactjs,Redux,我收到了以下警告: 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

我收到了以下警告:

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 );
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()
      }
    }
  }
堆栈跟踪:


我通过将调度从register components render方法删除到componentwillunmount方法,解决了这个问题。这是因为我希望这个逻辑在重定向到登录页面之前发生。一般来说,最好的做法是将所有逻辑放在render方法之外,这样我的代码以前写得很糟糕。希望这对以后的其他人有所帮助:)

我的重构寄存器组件:

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>
    );
  }
}

类寄存器扩展组件{
组件将卸载(){
//重置寄存器状态以允许返回到寄存器页面
如果(this.props.registerStatus!==“”)this.props.dispatch(resetRegisterStatus())
}
render(){
如果(this.props.registerStatus==SUCCESS){
返回
}
返回(
);
}
}

这太疯狂了。但是尝试禁用Redux开发工具。。。由于Redux开发工具,我在一个好的代码中显示了这个警告。我是在研究了为什么我的行为会触发多次后发现这一点的,尽管我只发送了一次

此警告是从React V16.3.0开始引入的。
如果您使用的是功能组件,则可以将setState调用包装为useffect。
不起作用的代码:

const HomePage = (props) => {
    
    props.setAuthenticated(true);

  const handleChange = (e) => {
    props.setSearchTerm(e.target.value.toLowerCase());
  };

  return (
    <div key={props.restInfo.storeId} className="container-fluid">
      <ProductList searchResults={props.searchResults} />
    </div>
  );
};
const主页=(道具)=>{
props.setAuthenticated(true);
常数handleChange=(e)=>{
props.setSearchTerm(e.target.value.toLowerCase());
};
返回(
);
};
现在您可以将其更改为:

const HomePage = (props) => {
  // trigger on component mount
  useEffect(() => {
    props.setAuthenticated(true);
  }, []);

  const handleChange = (e) => {
    props.setSearchTerm(e.target.value.toLowerCase());
  };

  return (
    <div key={props.restInfo.storeId} className="container-fluid">
      <ProductList searchResults={props.searchResults} />
    </div>
  );
};
const主页=(道具)=>{
//组件安装上的触发器
useffect(()=>{
props.setAuthenticated(true);
}, []);
常数handleChange=(e)=>{
props.setSearchTerm(e.target.value.toLowerCase());
};
返回(
);
};

致以最诚挚的问候,

我之所以来到这里,是因为我刚刚遇到了这个问题,在我意识到自己做错了什么之前,我花了一些时间仔细研究——我只是没有注意到我是如何编写我的功能组件的

我想我会在这里留下一个答案,以防有人来看,他们犯了和我一样的简单错误

我是这样做的:

const LiveMatches = (props: LiveMatchesProps) => {
  const {
    dateMatches,
    draftingConfig,
    sportId,
    getDateMatches,
  } = props;

  if (!dateMatches) {
    const date = new Date();
    getDateMatches({ sportId, date });
  };

  return (<div>{component stuff here..}</div>);
};

这是一个简单而愚蠢的错误,但我花了一段时间才意识到这一点,所以希望这能帮助其他人解决这个问题。

这是一个很大的失误,但我能够解决这个问题,因为我们的体系结构主要是类组件,而useState不可用

修复方法是使用一个简单的超时(同样,这仅适用于使用类组件的情况)

setTimeout(()=>,0);

这将推送到事件循环中。不管怎样,这仍然是一个黑客解决方案。我宁愿将其转换为功能组件,并用useState()将其包围起来,或者总体上避免这种架构

这里有一个大线索:。你能发布stacktrace(不是全部,只是相关部分)或告诉我们它所指的行吗?@RedBaron补充道stacktrace你也可以做一些解释,例如:
const{someDispatch}=props,然后在任何地方使用分派。如果希望只运行一次(而不是每次状态更新),则应将第二个参数
[]
添加到
useffect
。这为我修复了它。现在我想弄清楚原因。有什么帮助吗?@sawyerrken可能会回答部分原因,但总的来说,当我试图解决这个错误时,这个问题仍然困扰着我。你们刚刚救了我一个早上!在我的情况下,我通过移动
useffect
中的
dispatch
进行修复,谢谢,这为我修复了它。哦,伙计。我刚看到你的答案,马上就明白了错误所在。非常感谢。帮了我很多忙
const LiveMatches = (props: LiveMatchesProps) => {
  const {
    dateMatches,
    draftingConfig,
    sportId,
    getDateMatches,
  } = props;

  useEffect(() => {
    if (!dateMatches) {
      const date = new Date();
      getDateMatches({ sportId, date });
    }
  }, [dateMatches, getDateMatches, sportId]);

  return (<div>{component stuff here..}</div>);
};
setTimeout(() => <problematic dispatch goes here>, 0);