What's the '@' (at symbol) in the Redux @connect decorator?

The @ symbol is in fact a JavaScript expression currently proposed to signify decorators:

Decorators make it possible to annotate and modify classes and properties at design time.

Here's an example of setting up Redux without and with a decorator:

Without a decorator

import React from 'react';
import * as actionCreators from './actionCreators';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';

function mapStateToProps(state) {
  return { todos: state.todos };
}

function mapDispatchToProps(dispatch) {
  return { actions: bindActionCreators(actionCreators, dispatch) };
}

class MyApp extends React.Component {
  // ...define your main app here
}

export default connect(mapStateToProps, mapDispatchToProps)(MyApp);

Using a decorator

import React from 'react';
import * as actionCreators from './actionCreators';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';

function mapStateToProps(state) {
  return { todos: state.todos };
}

function mapDispatchToProps(dispatch) {
  return { actions: bindActionCreators(actionCreators, dispatch) };
}

@connect(mapStateToProps, mapDispatchToProps)
export default class MyApp extends React.Component {
  // ...define your main app here
}

Both examples above are equivalent, it's just a matter of preference. Also, the decorator syntax isn't built into any Javascript runtimes yet, and is still experimental and subject to change. If you want to use it, it is available using Babel.


Very Important!

These props are called state props and they are different from normal props, any change to your component state props will trigger the component render method again and again even if you don't use these props so for Performance Reasons try to bind to your component only the state props that you need inside your component and if you use a sub props only bind these props.

example: lets say inside your component you only need two props:

  1. the last message
  2. the user name

don't do this

@connect(state => ({ 
   user: state.user,
   messages: state.messages
}))

do this

@connect(state => ({ 
   user_name: state.user.name,
   last_message: state.messages[state.messages.length-1]
}))