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);
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;
Related Questions
- → How to update data attribute on Ajax complete
- → October CMS - Radio Button Ajax Click Twice in a Row Causes Content to disappear
- → Octobercms Component Unique id (Twig & Javascript)
- → Passing a JS var from AJAX response to Twig
- → Laravel {!! Form::open() !!} doesn't work within AngularJS
- → DropzoneJS & Laravel - Output form validation errors
- → Import statement and Babel
- → Uncaught TypeError: Cannot read property '__SECRET_DOM_DO_NOT_USE_OR_YOU_WILL_BE_FIRED' of undefined
- → React-router: Passing props to children
- → ListView.DataSource looping data for React Native
- → Can't test submit handler in React component
- → React + Flux - How to avoid global variable
- → Webpack, React & Babel, not rendering DOM