I want to fire an action down in my component. This is a presentation component and need not be redux aware. Router implementation is done using react-router-redux.
main.js:
let store = createStore(rootReducer)
const history = syncHistoryWithStore(hashHistory, store)
class RenderClass extends Component {
render() {
return (
<Provider store={store}>
<Router history={history}>
<Route path="/" component={MainLayout}>
<Route name="employees" path="/employees" url="http://localhost:8080/" component={EmployeeTable}></Route>
<Route name="personalInformation" path="/personalInformation/:employeeId" url={URI} component={PersonalInformation} />
.....
</Route>
<Router>
</Provider>
);
}
}
App.jsx:
import * as Actions from './action-creator';
const MainLayout = React.createClass({
render: function() {
const { dispatch, list } = this.props;
let actions = bindActionCreators(Actions, dispatch);
console.log(actions);
return (
<div className="wrapper">
<Header actions={actions} list={list} params={this.props.params} />
{React.cloneElement(this.props.children, this.props)}
</div>
)
}
});
function select(state) {
return {
list: state.listingReducer
}
}
export default connect(select)(MainLayout);
header.js:
define(
[
'react',
'jquery',
'appMin'
],
function (React, $) {
var Link = require('reactRouter').Link;
var Header = React.createClass({
handleClick: function () {
//Action called here
this.props.actions.listEmployees();
},
render: function () {
return (
<ul className="sidebar-menu">
<li>
<Link to={'/employees'} onClick={this.handleClick}><i className="fa fa-home"></i>Employees</Link>
</li>
</ul>
);
}
});
return Header;
}
)
employee.js:
define(
[
'react',
'jquery',
'appMin'
],
function (React, $) {
var EmployeeTable = React.createClass({
render: function () {
if (this.props.list != undefined) {
var listItems = this.props.list.map(function (listItem) {
return (
<tr key={listItem.id}>
<td> {listItem.name}</td>
<td><Link to={'/personalInformation/' + employee.id} onClick={this.props.actions.displayPersonalInformation(employee.id)}>Personal Information</Link></td>
......
</tr>
);
}, this);
})
}
return (
<table>
<tbody>
{listItems}
</tbody>
</table>
);
}
})
}
)
action-creator.js:
export function listEmployees() {
return {
type: types.LIST_EMPLOYEES
};
}
export function displayPersonalInformation() {
return {
type: types.DISPLAY_PERSONAL_INFORMATION
};
}
reducer.js:
function addEmployee(state, action) {
switch (action.type) {
case types.LIST_EMPLOYEES:
return {"id":"1", "name":"Stackoverflow"}
default:
return state
}
}
function listingReducer(state = [], action) {
switch (action.type) {
case types.LIST_EMPLOYEES:
return [
...state,
addEmployee(undefined, action)
]
case types.DISPLAY_PERSONAL_INFORMATION:
return // Gets personal Information
default:
return state;
}
}
const rootReducer = combineReducers({
listingReducer
})
export default rootReducer
The props will not contain actions since I have not tied it to props. I tried writing mapStateToProps and mapDispatchToProps in App.js as shown below:
function mapStateToProps(state) {
return {
list: state.list
}
}
function mapDispatchToProps(dispatch) {
return { actions: bindActionCreators({ actionCreators }, dispatch) }
}
export default connect(mapStateToProps, mapDispatchToProps)(MainLayout) I'm getting dispatch is not a function error. The error statement actually sounds like a duplicate question in stackoverflow, but I would also like to know the purpose why I'm using mapDispatchToProps is also right. Thanks in advance.
You cannot access your actions through props because you are assigning your actions to the action attribute. The way you bind your actions to your props you could access your functions through this.props.actions.myFunction. If you want to call your actions directly through props connect your actions to your props like this:
So from what I understand you are using
export default connect(mapStateToProps, mapDispatchToProps)(MainLayout)
and trying to calldispatch
inMainLayout
.So from the react-redux documentation if you see you can call connect in following ways:-
connect()(//Component)
--> dispatch would be passed as propsconnect(mapStateToProps)(//Component)
--> dispatch would be passed as propsconnect(mapStateToProps,mapDispatchToProps)(//Component)
--> dispatch would not be passed as props to your componentIn scenario 3 the behavior is this way because
mapDispatchToProps
already has access to dispatch function. So you can bind your function to dispatch inmapDispatchToProps
and then pass on this function to your component.Example
The function you want to dispatch are
dispatchMe()
anddispatchMe2()
which calls an action calleddispatchAction
. So yourmapDispatchToProps
would be something like :-Now in your component you can pass
dispatchMe
and call it when required.You can read here for more info on this
Since you have used
bindActionCreators
,redux
woulddispatch
the action whenever you call the action creator i.edisplayPersonalInformation
in your case.As @Harkirat Saluja mentioned in his answer, if you have used
mapDispatchToProps
then your component would not have thedispatch
function bound withprops
.But still if you want to have
dispatch
withprops
(not best practice), then you can have something like,