分派操作未调用Thunk Action-使用Typescript

问题描述 投票:0回答:2

我正在使用React,Redux,Redux-Thunk和Typescript(noobie)。当我使用重击调用动作时,可以看到该动作被调用(使用console.log),而调度未被调用。我已经使用mapToDispatch连接了此动作,并使用this.props。(action)从组件中调用了它。我不知道为什么不调用调度。这是我的代码:

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))
  }
}

容器

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>
    )
  }
}
reactjs typescript redux redux-thunk
2个回答
0
投票

似乎您正在分派thunk动作,但是您实际上并没有在thunk动作中分派动作。

[当分派一个动作getSearchResults时,将返回一个将dispatch方法作为参数的函数,您已经在return (dispatch) => {中正确指出了该函数。您可以使用该调度方法来调度进一步的操作。

您必须调用该调度方法才能生效。可能需要在promise回调中执行此操作,以处理从API调用返回的数据,然后将其存储在redux中。有点像...

export function getSearchResults (): ThunkAction<void, StoreShape, void, Action> {
  return (dispatch) => {
    const body: object = {
     ...
    }

    axios.post(
      'https://' + getAPIDomain() + '/proxy-service/ROOT/search/_search',
      body
    )
    .then((response: object): void => {
      const data = extractData(response)

      dispatch({
       type: UPDATE_SEARCH_RESULTS,
       payload: data,
      })
    })
    .catch((response: object):any => console.log(response))
  }
}

然后您应该在减速器中收到该UPDATE_SEARCH_RESULTS操作。

[如果您打算对API调用大量使用redux操作,强烈建议使用像https://www.npmjs.com/package/redux-api-middleware这样的中间件来为您保持干净。


0
投票

我发现映射这样的调度可以解决我的问题-但我不是100%知道为什么...:

const mapDispatchToProps = (dispatch: any, ownProps: OwnProps): DispatchProps => {
  return {
    getSearchResults: () => dispatch(getSearchResults()),
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.