Що таке mapDispatchToProps?


358

Я читав документацію для бібліотеки Redux, і в ній є такий приклад:

Крім зчитування стану, компоненти контейнера можуть відправляти дії. Аналогічним чином ви можете визначити функцію, яка називається, mapDispatchToProps()яка отримує dispatch()метод і повертає реквізит зворотного виклику, який ви хочете ввести в презентаційний компонент.

Це насправді не має сенсу. Навіщо вам це потрібно, mapDispatchToPropsколи вже є mapStateToProps?

Вони також надають цей зручний зразок коду:

const mapDispatchToProps = (dispatch) => {
  return {
    onTodoClick: (id) => {
      dispatch(toggleTodo(id))
    }
  }
}

Чи може хтось, будь ласка, пояснити лаїнською мовою, що це за функція і чому вона корисна?

Відповіді:


577

Я відчуваю, що жодна з відповідей не викристалізувала, чому mapDispatchToPropsце корисно.

На це дійсно можна відповісти лише в контексті container-componentшаблону, який я знайшов найкращим розумінням у першому читанні: Компоненти контейнерів, а потім використання з реагуванням .

Коротше кажучи, ваших, componentsяк передбачається, турбує лише показ зображень. Єдине місце , де вони повинні отримати інформацію від є їх реквізитом .

Від "відображення речей" (компонентів) відокремлено:

  • як ви можете відображати речі,
  • і як ви обробляєте події.

Це те containers, для чого.

Тому "добре розроблений" componentв шаблоні виглядає так:

class FancyAlerter extends Component {
    sendAlert = () => {
        this.props.sendTheAlert()
    }

    render() {
        <div>
          <h1>Today's Fancy Alert is {this.props.fancyInfo}</h1>
          <Button onClick={sendAlert}/>
        </div>
     }
}

Подивіться , як цей компонент отримує інформацію він відображає з реквізиту (який прийшов з Redux магазину через mapStateToProps) , і він також отримує функцію дії від її реквізиту: sendTheAlert().

Ось тут і mapDispatchToPropsйде: у відповідномуcontainer

// FancyButtonContainer.js

function mapDispatchToProps(dispatch) {
    return({
        sendTheAlert: () => {dispatch(ALERT_ACTION)}
    })
}

function mapStateToProps(state) {
    return({fancyInfo: "Fancy this:" + state.currentFunnyString})
}

export const FancyButtonContainer = connect(
    mapStateToProps, mapDispatchToProps)(
    FancyAlerter
)

Цікаво, чи можете ви бачити, тепер, коли це container 1, що знає про скорочення та відправлення, зберігання, стан та ... речі.

У componentшаблоні, FancyAlerterякий робить візуалізацію, не потрібно знати про будь-який з цих речей: він отримує свій спосіб викликати onClickкнопку, через реквізит.

І ... mapDispatchToPropsбув корисним засобом, який надає redux, щоб контейнер легко передавав цю функцію в загорнутий компонент на своїх реквізитах.

Все це дуже схоже на приклад todo в документах, і ще одна відповідь тут, але я намагався викласти це у світлі шаблону, щоб підкреслити, чому .

(Примітка: ви не можете використовувати mapStateToPropsз тією ж метою, що mapDispatchToPropsі з основної причини, коли ви не маєте доступу до dispatchвсередині mapStateToProp. Тож ви не могли використовувати mapStateToPropsдля того, щоб надати обгорнутому компоненту метод, який використовується dispatch.

Я не знаю, чому вони вирішили розбити його на дві функції картографування - можливо, було б акуратніше мати mapToProps(state, dispatch, props) IE одну функцію для виконання обох!


1 Зауважте, що я навмисно явно назвав контейнер FancyButtonContainer, щоб підкреслити, що це "річ" - ідентичність (і, отже, існування!) Контейнера як "речі" іноді втрачається у скороченні

export default connect(...) ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀

синтаксис, який показаний у більшості прикладів


5
Я все одно хотів би знати: Що з необхідною функціональністю не вдалося впоратися, безпосередньо зателефонувавши до store.dispatch всередині компонента?
піксельпакс

8
@ user2130130 Ні. Йдеться про хороший дизайн. Якщо ви з'єднали свій компонент з store.dispatch, тоді, коли ви вирішите виділити надмір, або хочете використовувати його в якомусь місці, яке не базується на Redxu (або іншому, про що я зараз не можу придумати), ви застрягли з багато змін. Ваше запитання узагальнює "чому ми не турбуємося про" хороші дизайнерські практики "- ти отримуєш таку ж функціональність, як тільки ти її кодуєш". mapDispatchToProps передбачений, щоб ви могли писати добре розроблені, чисто роз'єднані компоненти.
GreenAsJade

4
Чого я насправді не отримую, це те, що: ALERT_ACTIONце функція дії чи typeповертається з функції дії? : / так ошелешив
Джеймі Хатбер

1
@JamieHutber Строго, ALERT_ACTION не має нічого спільного з цим питанням. Це вагомий аргумент для відправки, і, як це відбувається, у моєму коді він походить від " конструктора дій", який повертає об'єкт, який диспетчер використовує, як описано redux.js.org/docs/api/Store.html#dispatch . Основний момент тут полягає в тому, що, як викликати відправлення, описано в контейнері і передається на реквізити компонентів. Компонент отримує функції лише від своїх реквізитів, ніде більше. "Неправильним" способом зробити це в цій схемі було б передати відправлення компоненту та здійснити той самий виклик у компоненті.
GreenAsJade

1
Якщо у вас є кілька творців дій, які потрібно передати дочірньому компоненту як реквізит, одна з альтернатив - обернути їх bindActionCreators всередині mapDispatchToProps (див. Redux.js.org/docs/api/bindActionCreators.html ); інша альтернатива - просто надати об’єктам дій, що створюють дії, щоб підключити (), наприклад, підключити (mapStateToProps, {actioncreators}), реакція-redux оберне їх dispatch () для вас.
Дейв

81

Це в основному стенограма. Тож замість того, щоб писати:

this.props.dispatch(toggleTodo(id));

Ви б використовували mapDispatchToProps, як показано у вашому прикладі коду, а потім пишіть:

this.props.onTodoClick(id);

або більше шансів у цьому випадку ви матимете це як обробник подій:

<MyComponent onClick={this.props.onTodoClick} />

Тут є корисне відео Дена Абрамова: https://egghead.io/lessons/javascript-redux-generating-containers-with-connect-from-react-redux-visibletodolist


Дякую. Мені також цікаво, як диспетчер в першу чергу додається до реквізиту?
Шепітер коду

14
Якщо ви не надаєте власну mapDispatchфункцію, Redux буде використовувати за замовчуванням. Ця mapDispatchфункція за замовчуванням просто приймає dispatchпосилання на функцію та надає її як this.props.dispatch.
markerikson

7
Метод відправки передається компонентом постачальника
Дієго Хаз

55

mapStateToProps()це утиліта, яка допомагає вашому компоненту оновити стан (який оновлюється іншими компонентами),
mapDispatchToProps()це утиліта, яка допоможе вашому компоненту розпочати дії події (диспетчерська дія, яка може спричинити зміну стану програми)


23

mapStateToProps, mapDispatchToPropsа connectз react-reduxбібліотеки надається зручний спосіб доступу до вашого магазину stateта його dispatchфункцій. Тому в основному підключення є компонентом вищого порядку, ви також можете вважати обгорткою, якщо це має сенс для вас. Таким чином, кожен раз, коли ваш stateзмінений mapStateToPropsбуде викликано ваш новий, stateа згодом, коли ви propsоновлюєте компонент, буде запущена функція візуалізації, щоб відобразити ваш компонент у браузері. mapDispatchToPropsтакож зберігає ключові значення propsвашого компонента, зазвичай вони набувають форми функції. Таким чином ви можете викликати stateзміни зі свого компонента onClick, onChangeподій.

З документів:

const TodoListComponent = ({ todos, onTodoClick }) => (
  <ul>
    {todos.map(todo =>
      <Todo
        key={todo.id}
        {...todo}
        onClick={() => onTodoClick(todo.id)}
      />
    )}
  </ul>
)

const mapStateToProps = (state) => {
  return {
    todos: getVisibleTodos(state.todos, state.visibilityFilter)
  }
}

const mapDispatchToProps = (dispatch) => {
  return {
    onTodoClick: (id) => {
      dispatch(toggleTodo(id))
    }
  }
}

function toggleTodo(index) {
  return { type: TOGGLE_TODO, index }
}

const TodoList = connect(
  mapStateToProps,
  mapDispatchToProps
)(TodoList) 

Також переконайтеся, що ви знайомі з функціями без громадянства React та компонентами вищого порядку


Тож відправка - це як подія в основному?
Code Whisperer

2
Це може бути пов'язано з подією, відправка - це лише функція і єдиний спосіб змінити стан вашої програми . mapStateToProps - це один із способів розкрити диспетчерську функцію вашого магазину на React Component. Також зауважте, що підключення не є частиною redux, насправді це лише утиліта та бібліотека скорочення шаблонів під назвою react-redux для роботи з react та redux. Ви можете домогтися того ж результату без реакції-скорочення, якщо передати свій магазин від компонента кореневої реакції дітям.
Влад Філімон

3

mapStateToPropsотримує stateі propsі дозволяє витягувати реквізити зі стану, щоб перейти до компонента.

mapDispatchToPropsотримує dispatchта propsпризначений для вас, щоб зв'язати творців дій для відправки, тому при виконанні отриманої функції дія буде відправлено.

Я вважаю, що це лише рятує вас від необхідності робити dispatch(actionCreator())ваш компонент, тим самим полегшуючи його читання.

https://github.com/reactjs/react-redux/blob/master/docs/api.md#arguments


Дякую, але яка цінність dispatchметоду? Звідки воно походить?
Шепітер коду

ой. В основному диспетчеризація змушує дію запустити однонаправлений потік / потік. Інші відповіді, здається, відповіли на ваше запитання краще за це.
Гаррі Морено

Також метод відправки походить від удосконалення, яке надає <Provider/>сам. Він робить власну магію компонентів високого порядку, щоб гарантувати, що відправка доступна для компонентів своїх дітей.
Рікардо Магалхес

3

Тепер припустимо, що існує дія для скорочення як:

export function addTodo(text) {
  return {
    type: ADD_TODO,
    text
  }
}

Коли ви імпортуєте його,

import {addTodo} from './actions';

class Greeting extends React.Component {

    handleOnClick = () => {
        this.props.onTodoClick(); // This prop acts as key to callback prop for mapDispatchToProps
    }

    render() {
        return <button onClick={this.handleOnClick}>Hello Redux</button>;
    }
}

const mapDispatchToProps = dispatch => {
    return {
      onTodoClick: () => { // handles onTodoClick prop's call here
        dispatch(addTodo())
      }
    }
}

export default connect(
    null,
    mapDispatchToProps
)(Greeting);

Як говорить назва функції mapDispatchToProps(), відображення dispatchдії на реквізит (реквізит нашого компонента)

Отже, опора onTodoClick- це ключ до mapDispatchToPropsфункціонування, який делегує все далі для відправки дій addTodo.

Крім того, якщо ви хочете обрізати код і обійти ручну реалізацію, ви можете це зробити,

import {addTodo} from './actions';
class Greeting extends React.Component {

    handleOnClick = () => {
        this.props.addTodo();
    }

    render() {
        return <button onClick={this.handleOnClick}>Hello Redux</button>;
    }
}

export default connect(
    null,
    {addTodo}
)(Greeting);

Що саме означає

const mapDispatchToProps = dispatch => {
    return {
      addTodo: () => { 
        dispatch(addTodo())
      }
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.