जब bindActionCreators प्रतिक्रिया / redux में उपयोग किया जाएगा?


91

बाइंडशन के लिए Redux डॉक्स यह बताता है कि:

इसके लिए एकमात्र उपयोग मामला bindActionCreatorsतब है जब आप कुछ एक्शन रचनाकारों को एक ऐसे घटक के पास भेजना चाहते हैं जो Redux से परिचित नहीं है, और आप इसे प्रेषण या Redux स्टोर को पास नहीं करना चाहते हैं।

एक उदाहरण क्या होगा जहाँ bindActionCreatorsइसका उपयोग / आवश्यकता होगी?

किस तरह के घटक Redux के बारे में पता नहीं होगा ?

दोनों विकल्पों के क्या फायदे / नुकसान हैं?

//actionCreator
import * as actionCreators from './actionCreators'

function mapStateToProps(state) {
  return {
    posts: state.posts,
    comments: state.comments
  }
}

function mapDispatchToProps(dispatch) {
  return bindActionCreators(actionCreators, dispatch)
}

बनाम

function mapStateToProps(state) {
  return {
    posts: state.posts,
    comments: state.comments
  }
}

function mapDispatchToProps(dispatch) {
  return {
    someCallback: (postId, index) => {
      dispatch({
        type: 'REMOVE_COMMENT',
        postId,
        index
      })
    }
  }
}

जवाबों:


58

मुझे नहीं लगता कि सबसे लोकप्रिय जवाब, वास्तव में सवाल का समाधान है।

नीचे दिए गए सभी उदाहरण अनिवार्य रूप से एक ही काम करते हैं और "पूर्व-बाध्यकारी" अवधारणा का पालन नहीं करते हैं।

// option 1
const mapDispatchToProps = (dispatch) => ({
  action: () => dispatch(action())
})


// option 2
const mapDispatchToProps = (dispatch) => ({
  action: bindActionCreators(action, dispatch)
})


// option 3
const mapDispatchToProps = {
  action: action
}

विकल्प #3केवल विकल्प के लिए एक आशुलिपि है #1, इसलिए असली सवाल यह है कि कोई विकल्प #1बनाम विकल्प का उपयोग क्यों करेगा #2। मैंने देखा है कि दोनों ने प्रतिक्रिया-रिड्यूक्स कोडबेस में उपयोग किया है, और मुझे लगता है कि यह भ्रामक है।

मुझे लगता है कि इस तथ्य से भ्रम पैदा होता है कि डॉक्टर में सभी उदाहरणों का react-reduxउपयोग करता है bindActionCreatorsजबकि बिंडऑक्शनक्रिएटर्स के लिए डॉक्टर (जैसा कि स्वयं प्रश्न में उद्धृत किया गया है) कहता है कि इसे प्रतिक्रिया-रिडक्स के साथ उपयोग न करें।

मुझे लगता है कि जवाब कोडबेस में स्थिरता है, लेकिन मैं व्यक्तिगत रूप से जब भी जरूरत होती है डिस्पैच में स्पष्ट रूप से रैपिंग एक्शन पसंद करता हूं ।


2
विकल्प के #3लिए विकल्प आशुलिपि कैसे है #1?
ogostos


@ArtemBernatskyi धन्यवाद। तो, बदल जाता है वहाँ के लिए 3 मामलों रहे हैं बाहर mapDispatchToProps: function, objectऔर याद आ रही। प्रत्येक मामले को कैसे
निपटाया

मैं इस जवाब की तलाश में हूं। धन्यवाद।
किशन राजदेव

मैं वास्तव में विशिष्ट उपयोग के मामले में आया हूं कि रिएक्ट डॉक्स के बारे में बात करते हैं "कुछ एक्शन रचनाकारों को एक घटक के पास करें जो Redux के बारे में पता नहीं है" क्योंकि मेरे पास एक सरल घटक है जो एक अधिक जटिल घटक से जुड़ा हुआ है और ओवरहेड को जोड़ रहा है। की reduxऔर connectऔर addDispatchToPropsकरने के लिए सरल घटक overkill लगता है कि अगर मैं सिर्फ एक प्रोप नीचे पारित कर सकते हैं। लेकिन जहाँ तक मुझे पता है mapDispatchकि प्रॉप्स के लिए लगभग सभी मामले या तो विकल्प होंगे #1या #3उत्तर में उल्लिखित होंगे
icc97

48

99% समय, इसका उपयोग पैरामीटर के connect()भाग के रूप में रिएक्ट-रिडक्स फ़ंक्शन के साथ किया जाता है mapDispatchToProps। यह mapDispatchआपके द्वारा प्रदान किए गए फ़ंक्शन के अंदर या स्वचालित रूप से उपयोग किया जा सकता है , या स्वचालित रूप से यदि आप ऑब्जेक्ट शॉर्टहैंड सिंटैक्स का उपयोग करते हैं और इसके लिए एक्शन क्रिएटर्स से भरा ऑब्जेक्ट पास करते हैं connect

विचार यह है कि एक्शन क्रिएटर्स को प्री-बाइंड करने से, आप जिस घटक को connect()तकनीकी रूप से पास करते हैं, वह "नहीं जानता" है कि यह जुड़ा हुआ है - यह सिर्फ जानता है कि इसे चलाने की आवश्यकता है this.props.someCallback()। दूसरी ओर, यदि आप एक्शन क्रिएटर्स को बांधते नहीं हैं, और कहते हैं this.props.dispatch(someActionCreator()), अब घटक "जानता है" यह जुड़ा हुआ है क्योंकि यह props.dispatchमौजूद होने की उम्मीद कर रहा है।

मैंने अपने ब्लॉग पोस्ट Idiomatic Redux में इस विषय पर कुछ विचार लिखे : एक्शन क्रिएटर्स का उपयोग क्यों करें?


1
लेकिन यह 'mapDispatchToProps' से जुड़ा है, जो ठीक है। ऐसा लगता है कि बाध्यकारी एक्शन निर्माता वास्तव में एक नकारात्मक / निरर्थक बात है क्योंकि आप डिबगिंग जैसी कई अन्य चीजों के बीच फ़ंक्शन परिभाषा (टीएस या फ्लो) खो देंगे। अपने नए प्रोजेक्ट्स पर मैं इसका इस्तेमाल कभी नहीं करता और मुझे आज तक कोई समस्या नहीं हुई। साथ ही सागा और हठ राज्य का उपयोग करना। इसके अलावा, यदि आप सिर्फ रिडक्स फ़ंक्शंस पर कॉल कर रहे हैं (आपको अच्छा क्लिक मिलता है) तो मैं कहूंगा कि यह क्लीनर भी है तो एक्शन क्रिएटर्स को 'अटैच' करना जो मेरी राय में गड़बड़ और व्यर्थ है। आपके स्मार्ट (आमतौर पर स्क्रीन घटक) अभी भी कनेक्ट का उपयोग कर सकते हैं, केवल प्रॉप्स के लिए हालांकि।
ओलिवर डिक्सन

19

अधिक पूर्ण उदाहरण, कनेक्ट करने के लिए एक्शन क्रिएटर्स से भरी वस्तु को पास करें:

import * as ProductActions from './ProductActions';

// component part
export function Product({ name, description }) {
    return <div>
        <button onClick={this.props.addProduct}>Add a product</button>
    </div>
}

// container part
function mapStateToProps(state) {
    return {...state};
}

function mapDispatchToProps(dispatch) {
    return bindActionCreators({
        ...ProductActions,
    }, dispatch);
}

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

इसका उत्तर होना चाहिए
दीन जॉन

16

मैं मूल सवालों के जवाब देने की कोशिश करूंगा ...

स्मार्ट और गूंगा घटक

अपने पहले प्रश्न में आप मूल रूप से पूछते हैं कि bindActionCreatorsपहली जगह की आवश्यकता क्यों है, और किस तरह के घटकों को Redux के बारे में पता नहीं होना चाहिए।

संक्षेप में विचार यह है कि घटकों को स्मार्ट (कंटेनर) और गूंगा (प्रस्तुति) घटकों में विभाजित किया जाना चाहिए । गूंगे घटक जरूरत के आधार पर काम करते हैं। उनकी आत्मा का काम HTML में दिए गए डेटा को रेंडर करना है और इससे ज्यादा कुछ नहीं। उन्हें आवेदन के आंतरिक कामकाज के बारे में पता नहीं होना चाहिए। उन्हें आपके आवेदन की त्वचा की गहरी परत के रूप में देखा जा सकता है।

दूसरी ओर स्मार्ट घटक एक गोंद की तरह होते हैं, जो गूंगा घटकों के लिए डेटा तैयार करता है और अधिमानतः कोई HTML प्रतिपादन नहीं करता है।

इस तरह की वास्तुकला यूआई परत और नीचे की परत के बीच ढीली युग्मन को बढ़ावा देती है। यह बदले में दो परतों में से किसी के साथ कुछ और (यानी यूआई का एक नया डिजाइन) के आसान प्रतिस्थापन की अनुमति देता है, जो अन्य परत को नहीं तोड़ देगा।

आपके प्रश्न का उत्तर देने के लिए: डंबल घटकों को Redux (या उस मामले के लिए डेटा-लेयर का कोई अनावश्यक कार्यान्वयन विवरण) के बारे में पता नहीं होना चाहिए क्योंकि हम भविष्य में इसे किसी और चीज़ से बदलना चाहते हैं।

आप इस अवधारणा के बारे में Redux मैनुअल में और डान अब्रामोव द्वारा प्रस्तुत लेख और कंटेनर घटकों में अधिक गहराई से जान सकते हैं।

कौन सा उदाहरण बेहतर है

दूसरा प्रश्न दिए गए उदाहरणों के फायदे / नुकसान के बारे में था।

में पहला उदाहरण कार्रवाई रचनाकारों एक अलग में परिभाषित कर रहे हैं actionCreators, फ़ाइल / मॉड्यूल जिसका मतलब है कि वे कहीं और पुन: उपयोग किया जा सकता है। यह क्रियाओं को परिभाषित करने का मानक तरीका है। मैं वास्तव में इसमें कोई कमी नहीं देखता हूं।

दूसरे उदाहरण कार्रवाई रचनाकारों इनलाइन को परिभाषित करता है, जो कई नुकसान हैं:

  • एक्शन क्रिएटर्स को फिर से इस्तेमाल नहीं किया जा सकता (जाहिर है)
  • बात अधिक क्रियात्मक है, जिसका अनुवाद कम पठनीय है
  • कार्रवाई प्रकार हार्ड कोडित हैं - यह अधिमानतः उन्हें constsअलग-अलग परिभाषित करने के लिए है , ताकि उन्हें रिड्यूसर में संदर्भित किया जा सके - जिससे टाइपिंग गलतियों के लिए एक मौका कम हो जाएगा
  • एक्शन क्रिएटर्स इनलाइन को परिभाषित करना उनके उपयोग के अनुशंसित / अपेक्षित तरीके के खिलाफ है - जो आपके कोड को समुदाय के लिए थोड़ा कम पठनीय बना देगा, यदि आप अपना कोड साझा करने की योजना बनाते हैं

दूसरे उदाहरण में पहले एक पर एक फायदा है - यह लिखने के लिए तेज़ है! इसलिए यदि आपके पास अपने कोड के लिए अधिक योजना नहीं है, तो यह ठीक हो सकता है।

मुझे आशा है कि मैं चीजों को थोड़ा स्पष्ट करने में कामयाब रहा ...


2

इसका एक संभावित उपयोग bindActionCreators()एक ही प्रोप के रूप में एक साथ कई क्रियाओं को "मैप" करना है।

एक सामान्य प्रेषण इस तरह दिखता है:

प्रॉम्प्ट के लिए कुछ सामान्य उपयोगकर्ता क्रियाओं को मैप करें।

const mapStateToProps = (state: IAppState) => {
  return {
    // map state here
  }
}
const mapDispatchToProps = (dispatch: Dispatch) => {
  return {
    userLogin: () => {
      dispatch(login());
    },
    userEditEmail: () => {
      dispatch(editEmail());
    },
  };
};
export default connect(mapStateToProps, mapDispatchToProps)(MyComponent);

बड़ी परियोजनाओं में प्रत्येक प्रेषण को अलग-अलग मैप करना अनिर्दिष्ट महसूस कर सकता है। यदि हमारे पास क्रियाओं का एक समूह है जो एक दूसरे से संबंधित हैं तो हम इन क्रियाओं को जोड़ सकते हैं । उदाहरण के लिए एक उपयोगकर्ता एक्शन फ़ाइल जिसने सभी प्रकार के विभिन्न उपयोगकर्ता संबंधित कार्य किए। प्रत्येक कार्रवाई को एक अलग प्रेषण के रूप में कॉल करने के bindActionCreators()बजाय हम उपयोग कर सकते हैं dispatch

BindActionCreators () का उपयोग करके कई डिस्पैच

अपने सभी संबंधित कार्यों को आयात करें। वे संभवतः Redux स्टोर में एक ही फ़ाइल में हैं

import * as allUserActions from "./store/actions/user";

और अब डिस्पैच उपयोग bindActionCreators का उपयोग करने के बजाय ()

    const mapDispatchToProps = (dispatch: Dispatch) => {
      return {
           ...bindActionCreators(allUserActions, dispatch);
        },
      };
    };
    export default connect(mapStateToProps, mapDispatchToProps, 
    (stateProps, dispatchProps, ownProps) => {
      return {
        ...stateProps,
        userAction: dispatchProps
        ownProps,
      }
    })(MyComponent);

अब मैं userActionआपके घटक के सभी कार्यों को कॉल करने के लिए प्रोप का उपयोग कर सकता हूं ।

IE: userAction.login() userAction.editEmail() या this.props.userAction.login() this.props.userAction.editEmail()

नोट: आपको bindActionCreators () को एक प्रोप में मैप करने की आवश्यकता नहीं है। (अतिरिक्त => {return {}}कि नक्शे userAction)। आप bindActionCreators()एक ही फाइल की सभी क्रियाओं को अलग-अलग प्रॉप के रूप में मैप करने के लिए भी उपयोग कर सकते हैं । लेकिन मुझे लगता है कि ऐसा करना भ्रामक हो सकता है। मैं प्रत्येक कार्रवाई या "कार्रवाई समूह" को एक स्पष्ट नाम देना पसंद करता हूं। मैं यह भी बताने के लिए पसंद करता हूं ownPropsकि ये "चाइल्ड प्रॉप्स" क्या हैं या वे कहां से आ रहे हैं। Redux + React का उपयोग करते समय यह थोड़ा भ्रमित हो सकता है जहां सभी प्रॉप्स की आपूर्ति की जा रही है ताकि अधिक वर्णनात्मक बेहतर हो।


2

उपयोग करके bindActionCreators, यह कई एक्शन फ़ंक्शंस को समूहीकृत कर सकता है और इसे एक ऐसे घटक के पास भेज सकता है जिसे Redux (डंब कंपोनेंट) की जानकारी नहीं है

// actions.js

export const increment = () => ({
    type: 'INCREMENT'
})

export const decrement = () => ({
    type: 'DECREMENT'
})
// main.js
import { Component } from 'react'
import { bindActionCreators } from 'redux'
import * as Actions from './actions.js'
import Counter from './counter.js'

class Main extends Component {

  constructor(props) {
    super(props);
    const { dispatch } = props;
    this.boundActionCreators = bindActionCreators(Actions, dispatch)
  }

  render() {
    return (
      <Counter {...this.boundActionCreators} />
    )
  }
}
// counter.js
import { Component } from 'react'

export default Counter extends Component {
  render() {
    <div>
     <button onclick={() => this.props.increment()}
     <button onclick={() => this.props.decrement()}
    </div>
  }
}

1

मैं bindActionsCreators के बारे में और अधिक जानना चाह रहा था और यहाँ बताया गया है कि मैं अपनी परियोजना में किस तरह से लागू किया गया।

// Actions.js
// Action Creator
const loginRequest = (username, password) => {
 return {
   type: 'LOGIN_REQUEST',
   username,
   password,
  }
}

const logoutRequest = () => {
 return {
   type: 'LOGOUT_REQUEST'
  }
}

export default { loginRequest, logoutRequest };

आपके रिएक्ट कंपोनेंट में

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import ActionCreators from './actions'

class App extends Component {
  componentDidMount() {
   // now you can access your action creators from props.
    this.props.loginRequest('username', 'password');
  }

  render() {
    return null;
  }
}

const mapStateToProps = () => null;

const mapDispatchToProps = dispatch => ({ ...bindActionCreators(ActionCreators, dispatch) });

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

0

एक के लिए अच्छा उपयोग के मामले bindActionCreatorsके साथ एकीकरण के लिए है redux-गाथा का उपयोग कर redux-गाथा-दिनचर्या । उदाहरण के लिए:

// routines.js
import { createRoutine } from "redux-saga-routines";
export const fetchPosts = createRoutine("FETCH_POSTS");
// Posts.js
import React from "react";
import { bindActionCreators } from "redux";
import { connect } from "react-redux";
import { fetchPosts } from "routines";

class Posts extends React.Component {
  componentDidMount() {
    const { fetchPosts } = this.props;
    fetchPosts();
  }

  render() {
    const { posts } = this.props;
    return (
      <ul>
        {posts.map((post, i) => (
          <li key={i}>{post}</li>
        ))}
      </ul>
    );
  }
}

const mapStateToProps = ({ posts }) => ({ posts });
const mapDispatchToProps = dispatch => ({
  ...bindActionCreators({ fetchPosts }, dispatch)
});

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(Posts);
// reducers.js
import { fetchPosts } from "routines";

const initialState = [];

export const posts = (state = initialState, { type, payload }) => {
  switch (type) {
    case fetchPosts.SUCCESS:
      return payload.data;
    default:
      return state;
  }
};
// api.js
import axios from "axios";

export const JSON_OPTS = { headers: { Accept: "application/json" } };
export const GET = (url, opts) =>
  axios.get(url, opts).then(({ data, headers }) => ({ data, headers }));
// sagas.js
import { GET, JSON_OPTS } from "api";
import { fetchPosts } from "routines";
import { call, put, takeLatest } from "redux-saga/effects";

export function* fetchPostsSaga() {
  try {
    yield put(fetchPosts.request());
    const { data } = yield call(GET, "/api/posts", JSON_OPTS);
    yield put(fetchPosts.success(data));
  } catch (error) {
    if (error.response) {
      const { status, data } = error.response;
      yield put(fetchPosts.failure({ status, data }));
    } else {
      yield put(fetchPosts.failure(error.message));
    }
  } finally {
    yield put(fetchPosts.fulfill());
  }
}

export function* fetchPostsRequestSaga() {
  yield takeLatest(fetchPosts.TRIGGER, fetchPostsSaga);
}

ध्यान दें कि इस पैटर्न को रिएक्ट हुक (प्रतिक्रिया 16.8 के रूप में) का उपयोग करके लागू किया जा सकता है ।


-1

डॉक्स बयान बहुत स्पष्ट है:

इसके लिए एकमात्र उपयोग मामला bindActionCreatorsतब है जब आप कुछ एक्शन रचनाकारों को एक ऐसे घटक के पास भेजना चाहते हैं जो Redux से परिचित नहीं है, और आप इसे प्रेषण या Redux स्टोर को पास नहीं करना चाहते हैं।

यह स्पष्ट रूप से एक उपयोग मामला है जो निम्नलिखित और केवल एक स्थिति में उत्पन्न हो सकता है:

कहते हैं, हमारे पास घटक A और B हैं:

// A use connect and updates the redux store
const A = props => {}
export default connect()(A)

// B doesn't use connect therefore it does not know about the redux store.
const B = props => {}
export default B

प्रतिक्रिया के लिए इंजेक्शन-फिर से करना: (ए)

const boundActionCreators = bindActionCreators(SomeActionCreator, dispatch)
// myActionCreatorMethod,
// myActionCreatorMethod2,
// myActionCreatorMethod3,

// when we want to dispatch
const action = SomeActionCreator.myActionCreatorMethod('My updates')
dispatch(action)

प्रतिक्रिया-रिड्यूस द्वारा इंजेक्ट: (बी)

const { myActionCreatorMethod } = props
<B myActionCreatorMethod={myActionCreatorMethod} {...boundActionCreators} />

निम्नलिखित में से ध्यान दिया गया?

  • हमने घटक A के माध्यम से Redux स्टोर को अपडेट किया, जबकि हम घटक B में Redux स्टोर से अनजान थे।

  • हम घटक A में अपडेट नहीं कर रहे हैं। यह जानने के लिए कि मेरा वास्तव में क्या मतलब है, आप इस पोस्ट को देख सकते हैं । मुझे आशा है कि आपके पास एक विचार होगा।


7
मुझे कुछ समझ में नहीं आया
vsync
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.