Ad

Cannot Update Component On Props Or State Change

I want browser to show EditMessage component (in Dashboard.js) if showEdit is true (see initState in MessageReducer.js) and CreateMessage component if showEdit is false but my code doesn‘t work. My app is not noticing state or props change in Dashboard.js.

I tried includingthis.setState method in Dashboard.js but I am getting an error: "Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate". I also tried to assign the value of showTypeForm directly to props and output it (see comments in Dashboard.js) but this approach didn't work either. I am not sure what lifecycle method to use.

My code looks like this. MessageSummary.js:

 import React, { Component } from 'react';
 import { connect } from 'react-redux';
 class MessageSummary extends Component {
    editClick = (e) => {
       e.preventDefault();
       this.props.editMessage('123', 'I love web development'); //test values
    }
    render() {
       return (
          <button className="edit-message" onClick={this.editClick}>Edit 
          Message</button> // this button changes showEdit in MessageReducer.js
       )
    }
 }
 const mapDispatchToProps = (dispatch) => {
    return {
       editMessage: (id, newMessage) => dispatch(editMessage(id, newMessage))
    }
 }
 export default connect(null, mapDispatchToProps)(MessageSummary); 

MessageActions.js:

export const editMessage = (id, newMessage) => {
  return (dispatch, getState, { getFirebase, getFirestore }) => {
    dispatch({
      type: "EDIT_MESSAGE"
    });
  }
}

RootReducer.js:

// importing everything
const rootReducer = combineReducers({
  message: messageReducer
});
export default rootReducer;

MessageReducer.js:

const initState = {
  showEdit: false
};
const messageReducer = (state = initState, action) => {
  switch (action.type) {
     case 'EDIT_MESSAGE':
         initState.showEdit = !initState.showEdit; // toggling showEdit
         return state;
     default:
        return state;
     }
  }
 export default messageReducer;

Dashboard.js:

// importing everything
class Dashboard extends Component {
   state = {
      showEdit: this.props.message.showEdit
   }

   render() {
      const { message } = this.props; // destructuring

      // this.setState({
        //  showEdit: message.showEdit
      // })

      // const showTypeForm = message.showEdit ? <EditMessage /> : <CreateMessage />;

      return (
        <div className="message-form">   
            {this.state.showEdit ? <EditMessage /> : <CreateMessage />}
            // {showTypeForm }
        </div>   
      )
    }
   const mapStateToProps = (state) => {
      return {
         message: state.message
      }
   }
 }
 export default connect(mapStateToProps)(Dashboard); 
Ad

Answer

There is something wrong in your reducer 'MessageReducer.js'. Here your directly mutating the 'initState' value which is against the reducer function specificataion. It should be a pure function and should not mutate the state, every time it should return a new state object.
Please try with below updated code in MessageReducer.js

const initState = {
  showEdit: false
};
const messageReducer = (state = initState, action) => {
  switch (action.type) {
     case 'EDIT_MESSAGE':
         let updatedState = Object.assign({},state,{showEdit:!state.showEdit}) ;
         return updatedState;
     default:
        return state;`enter code here`
     }
  }
 export default messageReducer;
Ad
source: stackoverflow.com
Ad