Как получить простую отправку из this.props с помощью connect w/Redux?

У меня есть простой компонент React, который я подключаю (сопоставление простого массива/состояния). Чтобы не ссылаться на контекст для магазина, я бы хотел получить "отправку" непосредственно из реквизита. Я видел, как другие использовали этот подход, но не имеют доступа к этому по какой-то причине:)

Ниже приведены версии каждой зависимости npm, которые я использую в настоящее время

"react": "0.14.3",
"react-redux": "^4.0.0",
"react-router": "1.0.1",
"redux": "^3.0.4",
"redux-thunk": "^1.0.2"

Вот компонент w/connect

class Users extends React.Component {
    render() {
        const { people } = this.props;
        return (
            <div>
                <div>{this.props.children}</div>
                <button onClick={() => { this.props.dispatch({type: ActionTypes.ADD_USER, id: 4}); }}>Add User</button>
            </div>
        );
    }
};

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

export default connect(mapStateToProps, {
    fetchUsers
})(Users);

Если вам нужно увидеть редуктор (ничего интересного, но здесь оно)

const initialState = {
    people: []
};

export default function(state=initialState, action) {
    if (action.type === ActionTypes.ADD_USER) {
        let newPeople = state.people.concat([{id: action.id, name: 'wat'}]);
        return {people: newPeople};
    }
    return state;
};

Если вам нужно посмотреть, как настроен мой маршрутизатор w/redux

const createStoreWithMiddleware = applyMiddleware(
      thunk
)(createStore);

const store = createStoreWithMiddleware(reducers);

var Route = (
  <Provider store={store}>
    <Router history={createBrowserHistory()}>
      {Routes}
    </Router>
  </Provider>
);

Обновление

выглядит, если я опускаю свою собственную рассылку в подключении (в настоящее время выше я показываю fetchUsers), я бы получил бесплатную отправку (просто не уверен, что так будет работать настройка с асинхронными действиями). Люди смешиваются и сопоставляются, или все это или ничего?

[mapDispatchToProps]

Ответ 1

По умолчанию mapDispatchToProps просто dispatch => ({ dispatch }).
Поэтому, если вы не укажете второй аргумент connect(), вы получите dispatch в качестве поддержки в своем компоненте.

Если вы передадите пользовательскую функцию в mapDispatchToProps, вы можете сделать что-либо с помощью функции.
Несколько примеров:

// inject onClick
function mapDispatchToProps(dispatch) {
  return {
    onClick: () => dispatch(increment())
  };
}

// inject onClick *and* dispatch
function mapDispatchToProps(dispatch) {
  return {
    dispatch,
    onClick: () => dispatch(increment())
  };
}

Чтобы сохранить некоторые сообщения, Redux предоставляет bindActionCreators(), который позволяет вам это сделать:

// injects onPlusClick, onMinusClick
function mapDispatchToProps(dispatch) {
  return {
    onPlusClick: () => dispatch(increment()),
    onMinusClick: () => dispatch(decrement())
  };
}

в это:

import { bindActionCreators } from 'redux';

// injects onPlusClick, onMinusClick
function mapDispatchToProps(dispatch) {
  return bindActionCreators({
    onPlusClick: increment,
    onMinusClick: decrement
  }, dispatch);
}

или даже короче, когда имена имен prop соответствуют именам создателей действия:

// injects increment and decrement
function mapDispatchToProps(dispatch) {
  return bindActionCreators({ increment, decrement }, dispatch);
}

Если вы хотите, вы можете добавить dispatch туда вручную:

// injects increment, decrement, and dispatch itself
function mapDispatchToProps(dispatch) {
  return {
    ...bindActionCreators({ increment, decrement }), // es7 spread syntax
    dispatch
  };
}

Нет официальных рекомендаций относительно того, следует ли вам это делать или нет. connect() обычно служит границей между компонентами Redux-aware и Redux-unaware. Вот почему мы обычно чувствуем, что не нужно вводить как создателей связанных действий, так и dispatch. Но если вам кажется, что вам нужно это сделать, не стесняйтесь.

Наконец, шаблон, который вы используете прямо сейчас, является ярлыком, который даже короче вызова bindActionCreators. Когда все, что вы делаете, это return bindActionCreators, вы можете опустить вызов, а не делать это:

// injects increment and decrement
function mapDispatchToProps(dispatch) {
  return bindActionCreators({ increment, decrement }, dispatch);
}

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

может быть записано как

export default connect(
  mapStateToProps,
  { increment, decrement } // injects increment and decrement
)(App);

Однако вам придется отказаться от этого красивого короткого синтаксиса, когда вам нужно что-то более обычное, например, передать dispatch.

Ответ 2

Обычно вы можете смешивать и сопоставлять в зависимости от того, что вам нужно.

Вы можете передать dispatch в качестве опоры, если это то, что вы хотите:

export default connect(mapStateToProps, (dispatch) => ({
    ...bindActionCreators({fetchUsers}, dispatch), dispatch
}))(Users);

Я не уверен, как fetchUsers используется (как функция async?), но вы обычно используете что-то вроде bindActionCreators для автоматической привязки отправки, и вам не придется беспокоиться об использовании dispatch непосредственно в подключенных компонентах.

Используя dispatch каталог, тип пары - немой, безстоящий компонент с сокращением. Что может сделать его менее портативным.

Ответ 3

Пока вы можете передать dispatch вниз как часть dispatchToProps, я бы рекомендовал избегать доступа к store или dispatch напрямую из ваших компонентов. Кажется, вам будет лучше обслуживать, передав созданного связанного действия в connect 2-й аргумент dispatchToProps

См. пример, который я опубликовал здесь fooobar.com/info/80867/... о том, как передать "уже связанного создателя действия" таким образом, что вашим компонентам не нужно напрямую знать о или зависят от хранилища/отправки.

Извините за краткий. Я обновлю дополнительную информацию.