Зачем нужен bindActionCreators?
bindActionCreators получает на вход объект с AC, либо функцию и возвращает объект с AC, обернутыми в вызов dispatch или в случае с функцией функцию обернутую в dispatch.
Если вы передаете в connect вторым аргументом объект:const mapDispatchToProps = {
  getProducts,
};
То ваш объект в процессе вызова connect будет передан в вызов bindActionCreators и каждый AC будет обернут в вызов dispatch.
Этот вариант записи, в вашем случае, является предпочтительным, так как он короче.
Ручное оборачивание AC в dispatch:const mapDispatchToProps = (dispatch, ownProps) => ({
  getProducts: () => dispatch(getProducts()),
});
Тут можно использовать второй аргумент ownProps, ограничить количество принимаемых AC аргументов или поменять их порядок, а так же передать дополнительные функции, которые не надо оборачивать в dispatch.
Вызов bindActionCreators на объекте с AC:cosnt mapDispatchToProps = dispatch => bindActionCreators(
  {
    getProducts,
  },
  dispatch,
);
В использовании такого варианта записи нет особого смысла, так как первый вариант записи короче.
Но можно ее видоизменить:const mapDispatchToProps = (dispatch, ownProps) => ({
  ...bindActionCreators(
    {
      ...productsActions,
      ...usersActions,
      ...ordersActions,
    },
    dispatch,
  ),
  () => getSomeOther(ownProps.someProp),
  notNeedsToWrapInDispatch,
})
В таком виде можно передать в bindActionCreators много AC как есть и отдельно передать дополнительные AC обернутые в dispatch, которые будут использовать ownProps или функции которые не надо оборачивать в dispatch.
 Доки (англ) 