Javascript - Saf ve Impure işlevleri


12

Ben ikisinin tanımlarını inceledim:

Saf işlevler, girişlerini değiştirmeye çalışmayan ve her zaman aynı girişler için aynı sonucu döndüren işlevlerdir.

Misal

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

Ve Impure işlevi kendi girdisini değiştiren işlevdir.

Misal

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

ReactJs resmi belgelerinden alınan tanımlar ve kod parçacıkları .

Şimdi birisi bana, React / Redux'da saf fonksiyonların gerekli olduğu saf olmayan fonksiyonları kullanmak için nasıl hata yapabilirim ?


4
Saf olmayan fonksiyonların yan etkileri vardır. window.getElementByIdVb gibi bir şey aynı işlevi aynı parametrelerle çalıştırmak yan etkilere bağlı olarak farklı sonuçlar olabilir. Burada redux başarısız olur.
Dominik

Yanıtlar:


10

Tepki ve Reduxher ikisinin de tahmin edilebilir bir tarzda çalışabilmesi için değişmezlikle birlikte saf fonksiyonlara ihtiyacı vardır.

Bu iki şeyi izlemezseniz, uygulamanızda hatalar bulunur; en yaygın olanı React/Reduxdeğişiklikleri izleyemez ve değişiklikleriniz sırasında yeniden işleme koyamaz state/prop.

Tepki açısından, aşağıdaki örneği göz önünde bulundurun:

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();
}

Durum, yalnızca özellik ekleyen durum nesnesi tarafından tutulur. Bu uygulama, uygulama mülkünü işler. Bir şey olduğunda durumu her zaman oluşturmamalı, ancak durum nesnesinde bir değişiklik olup olmadığını kontrol etmelidir.

Bunun gibi, durumumuzu pure functionetkilemek için kullandığımız bir efekt fonksiyonumuz var . Durumun değiştirilmesi gerektiğinde yeni bir durum döndürdüğünü ve değişiklik yapılmadığında aynı durumu döndürdüğünü görürsünüz.

Ayrıca shouldUpdate, === operatörünü kullanarak eski durumun ve yeni durumun aynı olup olmadığını kontrol eden bir fonksiyonumuz var .

Tepki açısından hata yapmak için aşağıdakileri yapabilirsiniz:

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;
}

Durumu doğrudan kullanarak ve effectsişlevi kullanarak hatalar da yapabilirsiniz .

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

Yukarıdakiler yapılmamalı ve effectsdurumu güncellemek için sadece işlev kullanılmalıdır.

Tepki açısından, biz diyoruz effectsolarak setState.

Redux için:

  1. Redux'un combineReducersyardımcı programı referans değişikliklerini kontrol eder.
  2. React-Redux connectyöntemi mapState, sarılmış bileşenin gerçekten yeniden oluşturulması gerekip gerekmediğini görmek için işlevlerden hem kök durumu hem de dönüş değerleri için başvuru değişikliklerini denetleyen bileşenler oluşturur.
  3. Zaman yolculuğunda hata ayıklama, pure functionsfarklı durumlar arasında doğru şekilde atlayabilmeniz için redüktörün hiçbir yan etkisi olmamasını gerektirir .

İndirgeyici olarak saf olmayan fonksiyonları kullanarak yukarıdaki üçünü kolayca ihlal edebilirsiniz.

Doğrudan redux belgelerinden aşağıdakiler alınır:

Buna redüktör denir, çünkü geçeceğiniz işlev türüdür Array.prototype.reduce(reducer, ?initialValue).
Redüktörün saf kalması çok önemlidir. Bir redüktör içinde asla yapmamanız gereken şeyler:

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

Aynı argümanlar verildiğinde, bir sonraki durumu hesaplamalı ve geri vermelidir. Sürpriz yok. Yan efektleri olmayan. API çağrısı yok. Mutasyon yok. Sadece bir hesaplama.


7

Basitçe söylemek gerekirse, devlet mutasyona uğratılamaz. Her değişiklik olduğunda devletin yeni bir örneği iade edilmelidir.

Bu kod doğru değil:

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
  }
}

Bu kod aşağıda saf bir işlev olarak yazıldığında, Bu gerçek dizinin kendisini değiştirmez dizinin yeni bir örneğini döndürür. Değişmezliği işlemek için immer gibi bir kütüphaneyi kullanmanızın nedeni budur

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

API çağrıları ekleyerek veya yan etkilere neden olan kodlar yazarak saf işlevleri kirletebilirsiniz.

Saf işlevler her zaman açık ve kendini açıklamalı olmalı ve neler olduğunu anlamak için 3 veya 4 başka işleve başvurmanızı gerektirmemelidir.

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

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

Tepki / Redux durumunda

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
   }
  }
}

Bu yapılmamalıdır . Bir connect fonksiyonu veya redüktör fonksiyonunun ihtiyaç duyduğu her şey argüman aracılığıyla sağlanmalı veya fonksiyonu içinde yazılmalıdır. Asla dışarıdan gelmemelidir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.