जावास्क्रिप्ट - शुद्ध बनाम प्रभाव कार्य


12

मैं दो की परिभाषाओं से गुजरा हूं:

शुद्ध कार्य वे हैं जो अपने इनपुट को बदलने का प्रयास नहीं करते हैं, और हमेशा उसी इनपुट के लिए समान परिणाम लौटाते हैं।

उदाहरण

function sum(a, b) {
  return a + b;
}

और Impure फ़ंक्शन वह है जो अपना स्वयं का इनपुट बदलता है।

उदाहरण

function withdraw(account, amount) {
  account.total -= amount;
}

ReactJs के आधिकारिक डॉक्स से ली गई परिभाषाएं और कोड स्निपेट्स ।

अब, कोई मुझे बता सकता है, मैं अशुद्ध कार्यों का उपयोग करने के लिए रिएक्ट / रिडक्स में कुछ गलतियां कैसे कर सकता हूं , जहां शुद्ध कार्यों की आवश्यकता होती है?


4
प्रभाव कार्यों के दुष्प्रभाव हैं। कुछ window.getElementByIdइसी तरह के मापदंडों के आधार पर समान फ़ंक्शन के साथ एक ही फ़ंक्शन चलाने के विभिन्न परिणाम हो सकते हैं। वह जगह है जहाँ Redux विफल होगा।
डोमिनिक

जवाबों:


10

प्रतिक्रियाशील और Reduxदोनों को शुद्ध अंदाज की जरूरत होती है ताकि वे अंदाज से अंदाजा लगा सकें कि वे एक प्रेडिक्टेबल फैशन में चल रहे हैं।

यदि आप इन दो चीजों का पालन नहीं करते हैं, तो आपके ऐप में बग होंगे, सबसे आम React/Reduxबदलावों को ट्रैक करने में सक्षम नहीं है और आपके state/propपरिवर्तनों को फिर से प्रस्तुत करने में असमर्थ हैं।

प्रतिक्रिया के संदर्भ में, निम्नलिखित उदाहरण पर विचार करें:

let state = {
    add: 0,
}

function render() {
    //...
}
//pure function
function effects(state,action) {
//following immutability while updating state, not directly mutating the state.
    if(action == 'addTen') {
        return {...state, add: state.add + 10} 
    }
    return state;
}

function shouldUpdate(s) {
    if(s === state){
        return false
    }
    return true
}

state = effects(state, 'addTen')if(shouldUpdate(state)) {
    render();
}

राज्य को राज्य वस्तु द्वारा धारण किया जाता है जिसने केवल संपत्ति को जोड़ा है। यह ऐप ऐप प्रॉपर्टी को रेंडर करता है। यह हमेशा कुछ भी होने पर राज्य को प्रस्तुत नहीं करना चाहिए, लेकिन यह जांचना चाहिए कि क्या राज्य वस्तु में कोई परिवर्तन हुआ है।

जैसे, हमारे पास एक प्रभाव कार्य है, pure functionजिसका उपयोग हम अपने राज्य को प्रभावित करने के लिए करते हैं। आप देखते हैं कि यह एक नया राज्य लौटाता है जब राज्य को बदलना होता है और उसी राज्य को वापस करता है जब कोई संशोधन की आवश्यकता नहीं होती है।

हमारे पास एक shouldUpdateफ़ंक्शन भी है जो === ऑपरेटर का उपयोग करके जांचता है कि क्या पुराना राज्य और नया राज्य समान है।

प्रतिक्रिया के संदर्भ में गलतियाँ करने के लिए, आप वास्तव में निम्न कार्य कर सकते हैं:

function effects(state,action) {

  doRandom(); // effects should only be called for updating state.
             // Doing any other stuff here would make effects impure.

    if(action == 'addTen') {
        return {...state, add: state.add + 10}
    }
    return state;
}

आप राज्य को सीधे सेट करके और effectsफ़ंक्शन का उपयोग न करके भी गलतियाँ कर सकते हैं ।

function doMistake(newValue) {
    this.state = newValue
}

ऊपर नहीं किया effectsजाना चाहिए और राज्य को अपडेट करने के लिए केवल फ़ंक्शन का उपयोग किया जाना चाहिए।

प्रतिक्रिया के संदर्भ में, हम फोन effectsके रूप में setState

Redux के लिए:

  1. combineReducersसंदर्भ परिवर्तनों के लिए Redux की उपयोगिता जांचती है ।
  2. रिएक्ट-रेडक्स की connectविधि उन घटकों को उत्पन्न करती है जो रूट स्टेट दोनों के लिए संदर्भ परिवर्तन की जांच करती है और mapStateफ़ंक्शन से रिटर्न मान देखने के लिए कि क्या लिपटे घटक को वास्तव में फिर से प्रस्तुत करने की आवश्यकता है।
  3. टाइम-ट्रैवल डिबगिंग के लिए आवश्यक है कि रिड्यूसर pure functionsबिना किसी साइड इफेक्ट के हो ताकि आप सही तरीके से विभिन्न राज्यों के बीच कूद सकें।

आप रिड्यूसर के रूप में अशुद्ध कार्यों का उपयोग करके आसानी से उपरोक्त तीनों का उल्लंघन कर सकते हैं।

निम्नलिखित को सीधे redux डॉक्स से लिया गया है:

इसे एक reducer कहा जाता है क्योंकि यह फ़ंक्शन का प्रकार है जिसे आप पास करेंगे Array.prototype.reduce(reducer, ?initialValue)
यह बहुत महत्वपूर्ण है कि reducer शुद्ध रहता है। ऐसी चीजें जो आपको किसी रेड्यूसर के अंदर नहीं करनी चाहिए

Mutate its arguments;
Perform side effects like API calls and routing transitions;
Call non-pure functions, e.g. Date.now() or Math.random().

उसी तर्कों को देखते हुए, इसे अगले राज्य की गणना करनी चाहिए और इसे वापस करना चाहिए। कोई आश्चर्य नहीं। कोई दुष्प्रभाव नहीं। कोई एपीआई कॉल नहीं। कोई उत्परिवर्तन नहीं। सिर्फ एक गणना।


7

बस कहा जाता है कि राज्य को उत्परिवर्तित नहीं किया जा सकता है। राज्य का एक नया उदाहरण हर बार लौटाया जाना चाहिए ताकि एक बदलाव हो

यह कोड सही नहीं है:

const initialStates = {    
  items: ['item1']
}

export const ItemMaster = (state = initialStates, action) => {    
  switch (action.type) {
    case TYPES.ADD_ITEM:            
    {
        state.items.push(action.item)
        return state
    }
    default:
      return state
  }
}

यह कोड जब नीचे एक शुद्ध फ़ंक्शन के रूप में लिखा जाता है, तो यह उस सरणी का एक नया उदाहरण देता है जो वास्तविक सरणी को स्वयं संशोधित नहीं करता है। यही कारण है कि आप की तरह एक पुस्तकालय का उपयोग करना चाहिए है इम्मेर संभाल अचल स्थिति के लिए

const initialStates = { 
  items: ['item1']
}

export const ItemMaster = (state = initialStates, action) => {    
  switch (action.type) {
    case TYPES.ADD_ITEM:            
    {

        state = {...state,items:state.items.concat(action.item)}
        return state
    }
    default:
      return state
  }
}

5

आप एपीआई कॉल या साइड इफेक्ट्स के परिणामस्वरूप कोड लिखने से शुद्ध कार्य को अशुद्ध बना सकते हैं।

शुद्ध कार्य हमेशा बिंदु और स्व-स्पष्टीकरण पर होना चाहिए, और आपको यह समझने की आवश्यकता नहीं है कि क्या हो रहा है यह समझने के लिए आपको 3 या 4 अन्य कार्यों का उल्लेख करना चाहिए।

// Pure Function
function USDtoEUR(USD, todayRate) {
  return USD * todayRate;
}

// Impure Function 
function USDtoEUR(USD) {
  const todayRate = getTodayRate();
  return USD * todayRate;
}

प्रतिक्रिया / कमी के मामले में

const mapState = async state => {
  const { data } = await whatDoINeed()

  let mappedState = {}

  if (data.needDolphin) {
    mappedState.dolphin = state.dolphin
  }

  if (data.needShark) {
    mappedState.shark= state.shark
  }

  return mappedState;
}

// Or for Redux Reducer
// Bad
{
  setData: (state, payload) => {
   const set = whatToSet()
   return {
     ...state,
     set.dolphin ? ...{ dolphin: payload.dolphin } : ...{},
     set.shark ? ...{ shark : payload.shark } : ...{},
   }
  }
}

// Good
{
  setData: (state, payload) => {
   return {
     ...state,
     // Just send only the things need
     // to be sent
     ...payload
   }
  }
}

ऐसा नहीं करना चाहिए । सब कुछ एक कनेक्ट फ़ंक्शन या रिड्यूसर फ़ंक्शन की ज़रूरतों को तर्क के माध्यम से या इसके फ़ंक्शन के भीतर लिखा जाना चाहिए। इसे कभी भी बाहर से नहीं मिलना चाहिए।

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