Dispatch isn't called when I use bindActionCreators
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)} />
);
}
}
Answer
There are a couple issues here that seem to be syntactical and unrelated to Redux; they could be copy-paste errors, or actual issues:
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 | ); | ^
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)} />
);
Related Questions
- → Import statement and Babel
- → should I choose reactjs+f7 or f7+vue.js?
- → Uncaught TypeError: Cannot read property '__SECRET_DOM_DO_NOT_USE_OR_YOU_WILL_BE_FIRED' of undefined
- → .tsx webpack compile fails: Unexpected token <
- → React-router: Passing props to children
- → ListView.DataSource looping data for React Native
- → React Native with visual studio 2015 IDE
- → Can't test submit handler in React component
- → React + Flux - How to avoid global variable
- → Webpack, React & Babel, not rendering DOM
- → How do I determine if a new ReactJS session and/or Browser session has started?
- → Alt @decorators in React-Native
- → How to dynamically add class to parent div of focused input field?