Depending on where you put your export
, you might end up with a perfectly functioning React-Redux connected component, or one that seems to ignore Redux entirely.
In other words, there’s a world of difference between this:
class Thing extends Component { ... }
export default connect(mapStateToProps)(Thing);
and this:
export class Thing extends Component { ... }
connect(mapStateToProps, mapDispatchToProps)(Thing);
If you set it up like the second example, you might notice all the React stuff works, but the Redux functions mapStateToProps
and mapDispatchToProps
never run.
connect
does not change the component
When you wrap a component with connect, like connect(...)(Thing)
, it’s important to understand that this returns a connected component, but it does not touch the original Thing
component at all.
In other words, running connect(...)(Thing)
, does not “connect the Thing
component,” not really. What it does is return a new component which is connected.
Export the Connected Component
So, when it comes time to export a component, you almost definitely want to export the connected one. To do that, make sure to put the export
before the connect
call, like this:
export default connect(...)(Thing);
Why Not Both?
It’s perfectly valid to export the unconnected component and the connected one. This can be useful for testing – say, when you want to test the component without having to set up a mock Redux store.
Here’s how you could export both the unconnected component and the connected component:
export class Thing extends React.Component {
render() {
return "whatever";
}
}
const mapState = state => ({ someValue });
const mapDispatch = { action1, action2 };
export default connect(mapState, mapDispatch)(Thing);
Notice that there are 2 exports. One of them is named and one of them is default, and that’s important because it affects how you will import them later.
Import a Connected Component
The general rule of thumb is this: if something is export default
, you will import it with no braces, like so:
// Thing.js
export default connect(...)(Thing);
// UserOfThing.js
import Thing from './Thing';
If you’re exporting a named value, like a class or function, then you’ll import it with braces:
// Thing.js
export function Thing() { ... }
// UserOfThing.js
import { Thing } from './Thing';
You can also think of this like “destructuring” the module, just like you can destructure an object: pull out specific properties of the module by putting their names in braces, or leave the braces off to get the whole module.