【问题标题】:How to fix "dispatch is not a function" error如何修复“调度不是函数”错误
【发布时间】:2019-11-22 19:19:08
【问题描述】:

我正在开发一个简单的 react-redux 项目,该项目根据用户提供的搜索词从 OMDB api 获取有关电影的信息。我目前无法尝试在搜索栏中输入文本以更新与要搜索的电影标题对应的存储值。我对 redux 的反应和完全陌生我之前只完成了另一个 redux 项目,并且我以与上次完全相同的方式设置了我的操作和减速器,但这次我遇到了“未捕获的 TypeError: dispatch 不是一个函数”。这不是我在上一个项目中遇到的问题,到目前为止我的 google 搜索也不是很有帮助。

我在谷歌上搜索了这个问题,只找到了一些结果,但似乎没有一个与我有完全相同的问题,它们涉及使用我没有在连接函数内部使用的 mapDispatchToProps。假设当您像我一样编写 mapStateToProps 时,分派应该只是作为道具传递给连接的组件,但是每当我尝试访问它时,我都会收到上述“未捕获的 TypeError:分派不是函数”错误。

这是我的组件的 index.js

import { connect } from 'react-redux';
import MovieSearch from './MovieSearchContainer';
import { 
  updateSearchTerm,
  getMovies
} from './movieSearchActions';

function mapStateToProps(state){
  return {
    title: state.movieSearch.title,
    year: state.movieSearch.year,
    plot: state.movieSearch.plot,
    released: state.movieSearch.released,
    runtime: state.movieSearch.runtime,
    genre: state.movieSearch.genre,
    plot: state.movieSearch.plot,
    ratings: {
      IMDB: state.movieSearch.ratings.IMDB,
      Metascore: state.movieSearch.ratings.Metascore
    },
    posterUrl: state.movieSearch.posterUrl,
    cachedMovies: state.movieSearch.cachedMovies
  };
}

export default connect(mapStateToProps)(MovieSearch);

这是我的行动

export function updateSearchTerm(searchTerm){
  return {
    type: "UPDATE_SEARCH_TERM",
    payload: { searchTerm }
  }
}

这是我的 jsx 组件

import React from 'react';
import PropTypes from 'prop-types';
import {
  updateSearchTerm,
  getMovies
} from './movieSearchActions';

export default class MovieSearchContainer extends React.Component 
{
  constructor(props) {
    super(props);

    this.handleUpdateSearchTerm = 
    this.handleUpdateSearchTerm.bind(this);
  }

  handleUpdateSearchTerm(event){
    const { dispatch } = this.props;
    const { value } = event.target;
    dispatch(updateSearchTerm(value));
  }

  render() {
    return (
      <div>
        <h1 className='text-center'>Movie Finder</h1>
        <input type='text' className='col-sm-11' id='searchBar' 
        onChange={ this.handleUpdateSearchTerm }/>
        <button type='button' id='getMovies' className='col-sm- 
        1'>Go!</button>
      </div>
    )
  }
}

MovieSearchContainer.propTypes = {
  store: PropTypes.object
}

这里是减速器

export default function movieSearchReducer(state = defaultState, 
action) {
  const { type, payload } = action;

  switch(type){
    case 'UPDATE_SEARCH_TERM': {
      return {
        ...state,
        title: payload.title
      }
    }

    default: {
      return state;
    }
  }
}

我希望页面上组件的搜索栏的更改会反映在 redux 存储中,但我只是收到此错误

【问题讨论】:

    标签: javascript reactjs redux react-redux


    【解决方案1】:

    我认为你应该在你的 jsx 文件中连接你的组件。然后就可以用 this.props.yourFunctionToDispatch 访问了

    import React from 'react';
    import { connect } from 'react-redux';
    import PropTypes from 'prop-types';
    import {
      updateSearchTerm,
      getMovies
    } from './movieSearchActions';
    
    class MovieSearchContainer extends React.Component 
    {
      constructor(props) {
        super(props);
    
        this.handleUpdateSearchTerm = 
        this.handleUpdateSearchTerm.bind(this);
      }
    
      handleUpdateSearchTerm(event){
        const { dispatch } = this.props;
        const { value } = event.target;
        dispatch(updateSearchTerm(value));
      }
    
      render() {
        return (
          <div>
            <h1 className='text-center'>Movie Finder</h1>
            <input type='text' className='col-sm-11' id='searchBar' 
            onChange={ this.handleUpdateSearchTerm }/>
            <button type='button' id='getMovies' className='col-sm- 
            1'>Go!</button>
          </div>
        )
      }
    }
    const mapStateToProps = state => {
      return {
        title: state.movieSearch.title,
        year: state.movieSearch.year,
        plot: state.movieSearch.plot,
        released: state.movieSearch.released,
        runtime: state.movieSearch.runtime,
        genre: state.movieSearch.genre,
        plot: state.movieSearch.plot,
        ratings: {
          IMDB: state.movieSearch.ratings.IMDB,
          Metascore: state.movieSearch.ratings.Metascore
        },
        posterUrl: state.movieSearch.posterUrl,
        cachedMovies: state.movieSearch.cachedMovies
      };
    }
    
    MovieSearchContainer.propTypes = {
      store: PropTypes.object
    }
    export default connect(mapStateToProps, {yourFunctionToDispatch})(MovieSearchContainer);
    

    【讨论】:

      【解决方案2】:

      dispatch 属性仅在您直接与 redux-store 交互时可用。当您定义类似mapDispatchToProps() 并将其作为第二个参数传递给connect() 时,dispatch 将传递给mapDispatchToProps()

      const mapDispatchToProps = (dispatch) => {
          return{
            actionCreator: (arg) => {
               dispatch(actionCreator(arg))
            }
          }
      }
      
      export default connect(mapStateToProps, mapDispatchToProps)(Component)
      

      如果您不想定义mapDispatchToProps(),您可以通过将对象传递给connect() 作为第二个参数来有效地绑定您的动作创建者。这将dispatch 隐式绑定到动作创建者:

      import React from "react";
      import PropTypes from "prop-types";
      import { connect } from "react-redux";
      import { updateSearchTerm, getMovies } from "./movieSearchActions";
      
      class MovieSearchContainer extends React.Component {
        constructor(props) {
          super(props);
      
          this.handleUpdateSearchTerm = this.handleUpdateSearchTerm.bind(this);
        }
      
        handleUpdateSearchTerm(event) {
          const { value } = event.target;
          this.props.updateSearchTerm(value);
        }
      
        render() {
          console.log(this.props.movies);
          return (
            <div>
              <h1 className="text-center">Movie Finder</h1>
              <input
                type="text"
                className="col-sm-11"
                id="searchBar"
                onChange={this.handleUpdateSearchTerm}
              />
              <button
                type="button"
                id="getMovies"
                className="col-sm- 
              1"
              >
                Go!
              </button>
            </div>
          );
        }
      }
      
      MovieSearchContainer.propTypes = {
        store: PropTypes.object
      };
      
      const mapStateToProps = state => {
         return {
           title: state.movieSearch.title,
           year: state.movieSearch.year,
           plot: state.movieSearch.plot,
           released: state.movieSearch.released,
           runtime: state.movieSearch.runtime,
           genre: state.movieSearch.genre,
           plot: state.movieSearch.plot,
           ratings: {
           IMDB: state.movieSearch.ratings.IMDB,
             Metascore: state.movieSearch.ratings.Metascore
           },
           posterUrl: state.movieSearch.posterUrl,
           cachedMovies: state.movieSearch.cachedMovies
         };
       };
      
      
      export default connect(
        mapStateToProps,
        {
          updateSearchTerm,
          getMovies
        }
      )(MovieSearchContainer);
      

      这样,您无需显式调用 dispatch 即可使用您的 action-creator。只需使用this.props.nameOfActionCreator()

      例如查看沙盒:https://codesandbox.io/s/simple-redux-7s1c0

      【讨论】:

      • 我相信这就是我首先拥有它的方式,但让我尝试一下并确保编辑:是的,我的代码中就是这样,我仍然遇到同样的错误,我一定是在发布时打错了这个问题,但我会在上面解决它,仍然得到同样的错误
      • @jayluvsdivn 甜!让我知道它是怎么回事:)
      • @khan 是对的,我的印象是你已经把它连接到了 redux。为了获得 dispatch prop,你仍然需要连接到你的 store。
      • 我认为这就是 index.js 内部的 connect 函数?
      • @jayluvsdivn noo,您需要将每个组件单独连接到商店:)。查看更新的解决方案。
      猜你喜欢
      • 2019-12-25
      • 2019-10-07
      • 1970-01-01
      • 2021-06-12
      • 2019-07-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-07
      • 2019-11-26
      相关资源
      最近更新 更多