Reputation: 829
In a small React/Redux app that I am writing, I have a thunk that looks as follow:
updateCategory(category){
return function(dispatch, getState){
dispatch({ type : types.UPDATE_CATEGORY, category });
dispatch({ type : locationTypes.UPDATE_CATEGORY_FOR_ALL_LOCATIONS, category });
}
}
complete code:
//Category Duck
import v4 from 'node-uuid';
import {types as locationTypes} from './locations'
export const types = {
UPDATE_CATEGORY:"UPDATE_CATEGORY"
};
const initialState = [];
export function reducer(state = initialState, action){
switch (action.type) {
case types.UPDATE_CATEGORY:
return state.map( item => item.id !== action.category.id ? item : {...action.category} );
default:
return state;
}
};
export const actions={
updateCategory(category){
return function(dispatch, getState){
dispatch({ type : types.UPDATE_CATEGORY, category });
dispatch({ type : locationTypes.UPDATE_CATEGORY_FOR_ALL_LOCATIONS, category });
}
}
}
//Location Duck
import v4 from 'node-uuid';
export const types = {
UPDATE_CATEGORY_FOR_ALL_LOCATIONS:"UPDATE_CATEGORY_FOR_ALL_LOCATIONS"
};
const initialState=[];
export function reducer(state = initialState, action){
switch (action.type) {
case types.UPDATE_CATEGORY_FOR_ALL_LOCATIONS:
return state.map(item => item.category.id !== action.category.id ? item : { ...item, 'category':{name:action.category.name, id:action.category.id} })
default:
return state;
}
};
export const actions={
updateCategoryForAllLocations(category){
return { type : types.UPDATE_CATEGORY_FOR_ALL_LOCATIONS, category}
}
}
//configStore
import { createStore, combineReducers, applyMiddleware, compose } from 'redux';
import { routerReducer, routerMiddleware } from 'react-router-redux';//, push
import logger from 'redux-logger';
import * as storage from './localstorage';
import throttle from 'lodash/throttle';
import reducers from './duckes/rootReducer'; // Or wherever you keep your reducers
import thunk from 'redux-thunk';
const persistedState = storage.loadState();
const configureStore = (history) => {
const store = createStore(
combineReducers({
...reducers,
// router: routerReducer
}),
persistedState,
applyMiddleware(thunk)
);
store.subscribe(throttle(() => {
storage.saveState( store.getState() )
}),1000);
return store;
}
export default configureStore;
when calling it from a UI click handler in a connected component like this:
updateCategory({id:1, name:'foo')
I get back Error: Actions must be plain objects. Use custom middleware for async actions.
Can you advice me on how to solve this or maybe explain why it is happening?
the component with the call looks as follows: /ManageCategoryPage
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import {actions as categoryActions} from '../../duckes/categories';
import CategoryForm from './CategoryForm';
import {getElementByID} from '../../utils';
class ManageCategoryPage extends Component {
constructor(props) {
super(props);
//Init state
this.state = {
'category' : Object.assign({},this.props.category),
'errors':{}
}
//Bind functions
this.saveCategory=this.saveCategory.bind(this);
this.updateCategoryState=this.updateCategoryState.bind(this);
this.categoryExists=this.categoryExists.bind(this);
}
updateCategoryState(event){
...
}
categoryExists(category){
...
}
saveCategory(event){
event.preventDefault();
const {category}=this.state;
this.props.actions.updateCategory(category);
this.props.history.push('/categories');
}
//Render
render(){
return (
<CategoryForm
category={this.state.category}
locations={this.props.locations}
onChange={this.updateCategoryState}
onSave={this.saveCategory}
errors={this.state.errors}/>
)
}
}
//Prop Types validation
ManageCategoryPage.propTypes={
category: PropTypes.object.isRequired,
locations: PropTypes.array.isRequired,
categories: PropTypes.array.isRequired,
actions: PropTypes.object.isRequired
};
//Redux connect
const mapStateToProps = ({locations, categories}, ownProps) => {
let category={id:'', name:''};
return {
category : getElementByID(categories, ownProps.match.params.id) || category,
locations : locations,
categories : categories
};
};
const mapDispatchToProps = (dispatch) => {
return {
'actions': bindActionCreators(categoryActions, dispatch)
};
};
export default connect(mapStateToProps, mapDispatchToProps)(ManageCategoryPage);
Upvotes: 1
Views: 4607
Reputation: 829
I have found the issue and actually it was a mistake of mine, I had two configStore files and I somehow imported an old version of the configStore file that i created previously and it was missing 'thunk' as a param in applyMiddleware() call, so it means that it was applyMiddleware() instead applyMiddleware(thunk).
Upvotes: 1