ReactJS/Redux - 纯与不纯的 Javascript 函数?

Muh*_*ooq 17 javascript reactjs redux

我已经浏览了 ReactJs官方文档中Pure 和 Impure Javascript 函数的定义

纯函数是不尝试改变其输入的函数,并且对于相同的输入总是返回相同的结果。

例子

function sum(a, b) {
  return a + b;
}
Run Code Online (Sandbox Code Playgroud)

不纯函数是一种改变自己输入的函数

例子

function withdraw(account, amount) {
  account.total -= amount;
}
Run Code Online (Sandbox Code Playgroud)

现在,有人能告诉我,我怎么能错误地使React/Redux中的函数变得不纯,在那里需要纯函数?

Uts*_*tel 12

React 和Redux两者都需要结合不变性的纯函数以可预测的方式运行。

如果您不遵循这两点,您的应用就会出现错误,最常见的是React/Redux无法跟踪更改以及更改时无法重新渲染state/prop

就 React 而言,请考虑以下示例:

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();
}
Run Code Online (Sandbox Code Playgroud)

状态由仅添加属性的状态对象持有。此应用程序呈现应用程序属性。它不应该总是在发生任何事情时呈现状态,而应该检查状态对象中是否发生了变化。

像这样,我们有一个效果函数,pure function我们用它来影响我们的状态。您会看到它在要更改状态时返回一个新状态,并在不需要修改时返回相同的状态。

我们还有一个shouldUpdate函数,它使用 === 运算符检查旧状态和新状态是否相同。

要在 React 方面犯错误,您实际上可以执行以下操作:

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;
}
Run Code Online (Sandbox Code Playgroud)

也可以通过直接设置状态而不使用effects函数来出错。

function doMistake(newValue) {
    this.state = newValue
}
Run Code Online (Sandbox Code Playgroud)

不应执行上述操作,应仅使用effects函数来更新状态。

在发生反应而言,我们所说的effects作为setState

对于 Redux:

  1. Redux 的combineReducers实用程序检查引用更改。
  2. React-Redux 的connect方法生成组件,检查根状态和mapState函数返回值的引用更改,以查看包装的组件是否确实需要重新渲染。
  3. 时间旅行调试要求 reducerpure functions没有副作用,以便您可以正确地在不同状态之间跳转。

您可以通过使用不纯函数作为 reducer 来轻松违反上述三项。

以下直接取自 redux 文档:

它被称为减速器,因为它是您将传递给Array.prototype.reduce(reducer, ?initialValue).
减速器保持纯净非常重要。在减速器中你永远不应该做的事情:

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

给定相同的参数,它应该计算下一个状态并返回它。没有惊喜。无副作用。没有 API 调用。没有突变。只是一个计算。


mud*_*sir 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
  }
}
Run Code Online (Sandbox Code Playgroud)

这段代码写成下面的纯函数时,它返回一个新的数组实例,它不会修改实际的数组本身。这就是你应该使用像immer这样的库来处理不变性的原因

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
  }
}
Run Code Online (Sandbox Code Playgroud)


Pus*_*kin 5

您可以通过添加 API 调用或编写导致副作用的代码来使纯函数变得不纯。

纯函数应始终切中要害且一目了然,不应要求您参考 3 或 4 个其他函数来了解发生了什么。

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

// Impure Function 
function USDtoEUR(USD) {
  const todayRate = getTodayRate();
  return USD * todayRate;
}
Run Code Online (Sandbox Code Playgroud)

在 React / Redux 的情况下

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

Run Code Online (Sandbox Code Playgroud)

不应该这样做。connect 函数或 reducer 函数所需的一切都必须通过参数提供或写入其函数中。它永远不应该从外面进来。