Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot update a component while rendering a different component warning

I am getting this warning in react:

index.js:1 Warning: Cannot update a component (`ConnectFunction`)  while rendering a different component (`Register`). To locate the  bad setState() call inside `Register`  

I went to the locations indicated in the stack trace and removed all setstates but the warning still persists. Is it possible this could occur from redux dispatch?

my code:

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

function which triggers the warning in my registerForm component called by register.js

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

Stacktrace:

Stacktrace

like image 996
Tamjid Avatar asked Jun 12 '20 02:06

Tamjid


People also ask

How do you update components to another?

You don't update a component from another. Instead: components render from a shared top level data model. Callbacks are passed down to components. Any one of them can trigger a data change on that data model through the callbacks.

Can I setState In render?

render() Calling setState() here makes it possible for a component to produce infinite loops. The render() function should be pure, meaning that it does not modify a component's state. It returns the same result each time it's invoked, and it does not directly interact with the browser.

What is a react memo?

React.memo is a higher order component. If your component renders the same result given the same props, you can wrap it in a call to React.memo for a performance boost in some cases by memoizing the result. This means that React will skip rendering the component, and reuse the last rendered result.

Can changes be made inside the component?

(1) While editing a component, you can't change the state of the component unless you click on the parent layer first.


2 Answers

This warning was introduced since React V16.3.0.

If you are using functional components you could wrap the setState call into useEffect.

Code that does not work:

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

Now you can change it to:

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>   ); }; 
like image 60
Emile ASTIH Avatar answered Oct 21 '22 09:10

Emile ASTIH


Just coming here because I just had this issue and it took me a bit of digging around before I realised what I'd done wrong - I just wasn't paying attention to how I was writing my functional component.

Figured I'd leave an answer here in case anyone comes looking, and they made the same simple mistake that I did.

I was doing this:

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

I had just forgotten to use useEffect before dispatching my redux call of getDateMatches()

So stupid and something I had been doing in every other component, haha.

So it should have been:

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

Simple and silly mistake, but took a while to realise it, so hopefully this helps out someone else with this issue.

like image 33
Brett East Avatar answered Oct 21 '22 09:10

Brett East