Dispatch isn't called when I use bindActionCreators

- 1 answer

Ad

I'm able to get an input to update my redux store onChange if I explicitly write out the dispatch function. Why does it stop working when I try to use bindActionCreators()?

not using bindActionCreators (this works)

@connect(
  state => ({}),
  dispatch => {
    return {
      onSearchChange: (term) => {
        dispatch(search(term));
      }
    };
  }
)

export default class SearchForm extends Component {
  render() {
    return (
      <input type="text" onChange={(event) => onSearchChange(event.target.value)} />
    );
  }
}

using bindActionCreators (this does not work. It never dispatches the action)

@connect(
  state => ({ categories: state.categories.data }),
  dispatch => bindActionCreators({search}, dispatch)
);

export default class SearchForm extends Component {
  render() {
    return (
      <input type="text" onChange={(event) => search(event.target.value)} />
    );
  }
}
Ad

Answer

Ad

There are a couple issues here that seem to be syntactical and unrelated to Redux; they could be copy-paste errors, or actual issues:

  1. Your second example contains a syntax error; there should not be a semicolon at the end of the decorator:

    repl: Leading decorators must be attached to a class declaration (4:1)
      2 |   state => ({ categories: state.categories.data }),
      3 |   dispatch => bindActionCreators({search}, dispatch)
      4 | );
        |  ^
    
  2. The functions you're calling in the event handler (in both examples) don't seem to be defined; for them to work as written, you'd need to extract the function from this.props:

    export default class SearchForm extends Component {
      render() {
        const { search } = this.props;
        return (
          <input type="text" onChange={(event) => search(event.target.value)} />
        );
      }
    }
    

    If the examples are as written here in your code, I would expect the first example to fail unless there was an onSearchChange function declared in scope.

As a shortcut, connect can accept a simple object as a second argument, and it will assume each value on the object is an action creator for it to bind to:

@connect(
  state => ({ categories: state.categories.data }),
  { search }
)
export default class SearchForm extends Component {

[Edit]

Since you import search via

import {search} from 'redux/modules/repo-search';

you can import it instead with an alias

import { search as searchActionCreator } from 'redux/modules/repo-search';

If you do this, then connect needs to know the value you really want to use for the prop:

@connect(
  state => ({ categories: state.categories.data }),
  {search: searchActionCreator}
)
export default class SearchForm extends Component {
  render() {
    const { search } = this.props;
    return (
      <input type="text" onChange={(event) => search(event.target.value)} />
    );
  }
}

Alternatively, simply use a different variable name, or the path to the function in this.props, inside render:

return (
  <input type="text" onChange={(event) => this.props.search(event.target.value)} />
);
Ad
source: stackoverflow.com
Ad