Reputation: 645
I'm having a problem adding new object to array of objects through dispatching action after submit. The purpose of this is showing flash messages across site. I have two components that are responsible for showing messages, FlashMessagesList and FlashMessage. Also server respond with message object, that needs to bee added to messages array. The problem is when action is dispatched, I can see that it is dispatched in redux devtools, but state never changed no meter what i do, it remains empty array, and I'm quite stuck with this, so any advice will be welcome. Here is the relevant code:
/* flashMessagesList component */
import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import FlashMessage from './FlashMessage';
import { deleteFlashMessage } from '../../actions/actionFlashMessage';
class FlashMessagesList extends Component { //this is conected component cause we need data from store
render() {
const messages = this.props.messages.map(message =>
<FlashMessage key={message.id} message={message} deleteFlashMessage={this.props.deleteFlashMessage}/>
);
return (
<div>{messages}</div>
);
}
}
function mapStateToProps(state) {
return { //here we take a slice of global state
messages: state.flash.messages //define this in root reducer
};
}
function mapDispatchToProps(dispatch) {
return {
deleteFlashMessage: () => dispatch(deleteFlashMessage())
};
}
FlashMessagesList.propTypes = { //what this component will take
messages: PropTypes.arrayOf(
PropTypes.shape({
id: PropTypes.string.isRequired,
style: PropTypes.string.isRequired,
text: PropTypes.string.isRequired
})
),
deleteFlashMessage: PropTypes.func.isRequired
};
export default connect(mapStateToProps, mapDispatchToProps)(FlashMessagesList); //pass message from store to this component
/* flashMessage component */
import React, { Component, PropTypes } from 'react';
import classnames from 'classnames';
class FlashMessage extends Component {
deleteFlashMessage = () =>{
this.props.deleteFlashMessage(this.props.message.id); //dispatch some action that it has on it props
}
render() {
const { id, style, text } = this.props.message; //we can deconstruct message cause it is object
return (
<div className={classnames('alert', {
'alert-success': style === 'success',
'alert-danger': style === 'danger'
})}
>
{ text }
<button className="close" onClick={this.deleteFlashMessage}><span>×</span></button>
</div>
);
}
}
FlashMessage.propTypes = {
message: PropTypes.object.isRequired,
deleteFlashMessage: PropTypes.func.isRequired
};
export default FlashMessage;
/* reducerFlashMessage */
import * as types from '../actions/actionTypes';
import deepFreeze from 'deep-freeze';
import expect from 'expect';
const INITIAL_STATE = {
messages: []
};
const reducerFlashMessage = (state = INITIAL_STATE, action) => {
switch (action.types) {
case types.ADD_FLASH_MESSAGE:
return { ...state,
messages: [ ...state.messages, {
id: action.message.id,
style: action.message.style,
text: action.message.text
}]
};
}
return state;
};
export default reducerFlashMessage;
/* actionflashMessage */
import * as types from './actionTypes';
export function addFlashMessage(message) {
return {
type: types.ADD_FLASH_MESSAGE,
message
};
}
/* registerUser-place where i dispatch addFlashMessage */
export function registerUser({
timezone,
name,
email,
password,
passwordConfirmation
}) {
return dispatch => {
dispatch(isLoading(true));
axios.post('/auth/signup', {
timezone,
name,
email,
password,
passwordConfirmation
})
.then(response => {
dispatch(_registerUserSuccess(response.data.errors, response.data.message));
dispatch(isLoading(false));
dispatch(addFlashMessage(response.data.message));
dispatch(formReset());
// browserHistory.push('/signin');
setTimeout(() => {
// dispatch(_hideNotifications());
}, 2000);
// document.getElementById('form').reset();
})
.catch(error => {
if (error.response) {
dispatch(registerUserFailure(error.response.data.errors, error.response.data.message));
dispatch(isLoading(false));
dispatch(addFlashMessage(error.response.data.message));
}
else {
// Something happened in setting up the request that triggered an Error
console.log(error.message);
}
});
};
}
/* validation.js from server where i create message object*/
export function validateSignupForm(payload) {
const errors = {};
const message = {};
if(validator.isEmpty(payload.name)) {
errors.name = 'Name is required';
}
if(validator.isEmpty(payload.email)) {
errors.email = 'Email is required';
}
if(validator.isEmpty(payload.password)) {
errors.password = 'Password is required';
}
if(validator.isEmpty(payload.passwordConfirmation)) {
errors.passwordConfirmation = 'Password confirmation is required';
}
if(validator.isEmpty(payload.timezone)) {
errors.timezone = 'Timezone is required';
}
if (payload.email && !validator.isEmail(payload.email)) {
errors.email = 'Please provide a correct email address.';
}
if (payload.password && payload.password.length < 4) {
errors.password = 'Password must have at least 4 characters.';
}
if (payload.passwordConfirmation && !validator.equals(payload.password, payload.passwordConfirmation)) {
errors.password = 'Passwords must match.';
}
if (!isEmpty(errors)) {
message.id = shortid.generate(),
message.style = 'danger';
message.text = 'Check the form for errors.';
}
return {
success: isEmpty(errors),
message,
errors
};
}
Upvotes: 1
Views: 2347
Reputation: 4097
There's a typo in your reducer. Instead of
switch (action.types) {
should read
switch (action.type) {
Upvotes: 1