class SomeContainer extends Component {
//Like this
componentDidMount() {
dispatch(someAction())
}
}
You will need to use the store context:
containerXxx.contextTypes = {
store: React.PropTypes.object.isRequired
}
Then on your method, you can get dispatch function from store:
const store = this.context.store
store.dispatch(someAction())
Anyway, avoid doing this. The connect function should be fairly enough to link actions.
The comment in CounterContainer would seem to indicate that a container shouldn't have a componentDidMount() from React Component.
/* This is a container component. Notice it does not contain any JSX,
nor does it import React. This component is **only** responsible for
wiring in the actions and state necessary to render a presentational
component - in this case, the counter: */
Following that example, in your container the second argument of connect (mapActionCreators) will pass on the action creators that don't need a store reference (the functions are able to dispatch automatically). Then in the presentational component like the layout you can pass the actions creators (which are functions) through as props, so in your presentational component:
...'
componentDidMount() {
this.props.someAction()
}`
The starter kit is just a guide, so go with what works best for you. Search google for "abramov Presentational Container components" for more ideas.
The comment cited by @brianzinn is the core of your solution. A container does not concern itself with presentation; _simply said (sic)_ a pure container is not a React.Component... though directs 1..* React.Component.
See https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0#.eznb2j8bo
As @nie-xin eventually mentioned; connecting the component will give you access to dispatching actions;
import { someReduxAction } from './SomeReduxActions';
export class SomeView extends React.Component {
// someReduxAction is now available via this.props.someReduxAction
}
export default connect(null, {someReduxAction})(SomeView);
It all comes down to semantics.. your "container" is not a _container_ as people expect it to be. Though it is fine as it is. So how to do what you want to do?
Maybe something like;
import { someReduxAction } from './SomeReduxActions';
export class SomeView extends React.Component {
componentDidMount() {
this.props.someReduxAction();
}
}
export default connect(null, {someReduxAction})(SomeView);
As @nie-xin .
You will need to use the store context:
containerXxx.contextTypes = {
store: React.PropTypes.object.isRequired
}
in customize function, you should bind in
constructor (props, context) {
super(props, context)
this.functionName = this.functionName.bind(this)
}
functionName () {
const store = this.context.store
store.dispatch(someAction())
}
Closing as resolved, thanks for everybody's contributions.
@davezuko in some cases it would be nice to be able to handle this without passing the logic down to the presentational component and without the container having to extend React.Component.
I asked about this on Stack Overflow and have a possible solution that I'd be keen to get feedback on:
import { connect } from 'react-redux'
import MyComponent from '../components/mycomponent'
import { fetchMyData } from '../actions/mydata'
const mapStateToProps = state => ({
dataId: state.activeDataId,
myData: state.myData[state.activeDataId]
})
const mapDispatchToProps = { fetchMyData }
const mergeProps = (stateProps, dispatchProps) => {
if (!stateProps.myData) {
dispatchProps.fetchMyData(stateProps.dataId)
}
return stateProps
}
export default connect(mapStateToProps, mapDispatchToProps, mergeProps)(MyComponent)
I think that I understand what you are trying to do now. It looks like you are ensuring the data for your presentational component is available without wanting the presentation component to have that responsibility. I do agree that the presentational component should not have to take care of that, but feel personally that I don't want the container to do that either. One way is to put methods in routes. ie:
onEnter(next, replace) {
let activeDataId = next.params['id']
// route is dispatching selection.
store.dispatch(selectActiveData(Number(activeDataId)))
}
I don't normally use routes that way. Generally I handle these use-cases using redux-saga (there is a recipe available), so whenever state.activeDataId changed the saga (by listening for action(s)) would ensure the data was loaded (could also be done with a thunk) without side-effects. Doing so I have never needed a container to do anything besides map state and props. It's not hard to argue that a saga is overkill, so maybe more people would find your suggestion useful! :)
Most helpful comment
The comment cited by @brianzinn is the core of your solution. A container does not concern itself with presentation; _simply said (sic)_ a pure container is not a React.Component... though directs 1..* React.Component.
See https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0#.eznb2j8bo
As @nie-xin eventually mentioned; connecting the component will give you access to dispatching actions;
It all comes down to semantics.. your "container" is not a _container_ as people expect it to be. Though it is fine as it is. So how to do what you want to do?
Maybe something like;