I am using React, Redux, Redux-Thunk, and Typescript(noobie). When I call an action with a thunk, I can see that the action is called (using a console.log) but the dispatch is not. I have connected this action using mapToDispatch and call it from the Component using this.props.(action) . I can't figure out why the dispatch is not being called. Here is my code:
store.ts
import { applyMiddleware, combineReducers, createStore, Store, compose } from 'redux'
import { ReducerMap, StoreShape, SYSTEM_STATE_NAMESPACE_KEY } from './types'
import thunkMiddleware from 'redux-thunk'
import systemReducer from './globalData/reducer'
import { Environment, getCurrentEnvironment } from '../services/api.service'
let reducerMap: ReducerMap = { [SYSTEM_STATE_NAMESPACE_KEY]: systemReducer }
const isDevelopmentEnvironment = [Environment.LOCALHOST, Environment.STAGING].includes(getCurrentEnvironment())
export default function configureStore() {
const middleware = [thunkMiddleware]
const middlewareEnhancer = applyMiddleware(...middleware)
let composedEnhancers = isDevelopmentEnvironment
? (window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose
: compose
const preloadedState = (window as any).__PRELOADED_STATE__;
delete (window as any).__PRELOADED_STATE__;
return createStore(combineReducers(reducerMap), preloadedState, composedEnhancers(middlewareEnhancer))
}
export const store = configureStore()
export function getStore() {
return store
}
actions.js
import { SearchActionTypes, SearchNamespaceShape } from './types'
import axios from '../../../services/axiosInstance'
import { Action } from 'redux'
import { StoreShape } from '../../../store/types'
import { getAPIDomain } from '../../../services/api.service'
export function getSearchResults (): ThunkAction<void, StoreShape, void, Action> {
console.log('inside function')
return (dispatch) => {
console.log('inside dispatch')
const body: object = {
"query": {
"bool": {
"must": [
{
"match": {
"title": "CEO"
}
}
]
}
}
}
axios.post(
'https://' + getAPIDomain() + '/proxy-service/ROOT/search/_search',
body
)
.then((response: object):any => console.log(response))
.catch((response: object):any => console.log(response))
}
}
container
import { connect, Provider } from 'react-redux'
import * as React from 'react'
import { getStoreForSearch } from './data/store'
import { getGlobalData } from '../../store/globalData/selectors'
import UnconnectedSearchPage, { StateProps, DispatchProps, OwnProps } from './search'
import { StoreShape } from '../../store/types'
import { getSearchResults } from './data/actions'
const SearchContainer: React.FC = () => {
return (
<Provider store={getStoreForSearch({})} >
<ConnectedSearchPage textToDisplay='Hello World'/>
</Provider>)
}
function mapStateToProps (state: StoreShape, ownProps: OwnProps): StateProps {
return(
{
system: getGlobalData(state)
}
)
}
const mapDispatchToProps = (dispatch: any, ownProps: OwnProps): DispatchProps => ({
getSearchResults: () => dispatch(getSearchResults)
})
const ConnectedSearchPage = connect<StateProps, DispatchProps, OwnProps>(mapStateToProps, mapDispatchToProps)(
UnconnectedSearchPage
)
export default SearchContainer
component
import React from 'react'
import { ThunkAction } from 'redux-thunk'
import { Action } from 'redux'
import { GlobalDataNamespaceShape } from '../../store/globalData/types'
import { FullStoreShape } from '../../store/types'
export interface OwnProps {
textToDisplay: string
labelText?: string
}
export interface StateProps {
system: GlobalDataNamespaceShape
}
export interface DispatchProps {
getSearchResults: () => ThunkAction<void, Partial<FullStoreShape>, undefined, Action<object>>
}
export type SearchComponentProps = StateProps & DispatchProps & OwnProps
interface SearchState {
greeting: string
}
export default class UnconnectedSearchPage extends React.Component<SearchComponentProps, SearchState> {
constructor(props: SearchComponentProps) {
super(props)
this.state = { greeting: props.textToDisplay }
}
setGreeting( greeting: string): void {
this.setState({ greeting })
}
render () {
console.log(this.props)
return (
<div>
<h2>Search Page</h2>
<div>{`Greeting: ${this.state.greeting}`}</div>
<label>{this.props.labelText}</label>
<input
type='text'
value={this.state.greeting}
onChange={event => this.setGreeting(event.target.value)}
/>
<button onClick={() => {
this.props.getSearchResults()
}}>Get Search Results</button>
</div>
)
}
}