React-native和Redux健康方式调用道具更改

时间:2018-10-02 19:13:22

标签: node.js reactjs react-native redux react-redux

一段时间以来,我一直在用redux使用react-native,当prop发生更改时,我学会调用动作的方式是使用componentWillReceiveProps,但是当我使用它时,我需要在if和它之间传递如果出错,那么我需要添加更多的东西来防止它。

这是我做过的一个例子。我知道这不是最好的方法,但这是我能想到的。

componentWillReceiveProps(newProps) {
    if(Object.keys(newProps.selected_product).length > 0) {
        if(Object.keys(this.props.current_location).length > 0 || Object.keys(newProps.current_location).length > 0) {
            this._handleNextPage(2);
            this.props.verifyProductById(newProps.selected_product, newProps.current_location, this.props.token);
        } else {
            this.props.statusScanner(false);
            this._handleNextPage(1);
        }
    } else if(Object.keys(newProps.historic_product_confirm).length > 0) {
        if(newProps.historic_product_confirm.location._id == newProps.current_location._id)
            this.props.handleModalConfirmPrice(!this.props.modal_confirmPrice_status)
    } else if(newProps.scanResult != "") {
        this.props.statusScanner(false);
        if(Object.keys(newProps.current_location).length > 0) {
            this._handleNextPage(2);
        } else {
            this._handleNextPage(1);
        }
    } else {
        this._handleNextPage(0);
    }
}

当道具改变时,我需要一种健康的方式来称呼我的动作。

编辑: 这里有完整的OfferScene和操作文件示例:

OfferScene: https://gist.github.com/macanhajc/0ac98bbd2974d2f6fac96d9e30fd0642

UtilityActions: https://gist.github.com/macanhajc/f10960a8254b7659457f8a09c848c8cf

2 个答案:

答案 0 :(得分:0)

在代码的清晰性方面,我同意@AnuragChutani和@Goldy;将其分解为更多的组件或功能。

现在,在对componentWillReceiveProps函数进行一些检查之后,它绝对不够具体,不足以精确地缩小哪些prop更改。如果任何已连接的redux变量发生更改,则每次都会调用componentWillReceiveProps函数。

例如如果更新了“令牌”或“ selected_product”,即使您不希望它触发令牌更新,也会触发componentWillReceiveProps。

您可以在道具中使用比较来更新特定变量。 例如使用lodash

if(!_.isEqual( nextProps.selected_product, this.props.selected_product ))
// if props are different/updated, do something

第二,您可以在操作中调用操作/回调以缩小导航范围。 例如

takePicture = (camera, options){
  ...
  //on success
  dispatch(handleModalConfirmPrice())
  ...
}}

答案 1 :(得分:0)

如另一个答案中所述,componentWillReceiveProps正在被淘汰,所以我将力图尽可能地消除它。您将对代码进行过时的验证,并使组件逻辑更具声明性且易于推理。作为对这样的生命周期方法滥用负责(并为此感到沮丧)的人,以下是一些对我有所帮助的事情。

请记住,在使用redux-thunk时,将dispatch作为第一个参数传递,也可以将getState作为第二个参数传递。这使您可以在操作逻辑中访问状态值,而不必将其带入组件的属性并增加混乱。像这样:

export const ExampleAction = update =>
  (dispatch, getState) => {
    const { exampleBool } = getState().ExampleReducer

    if (exampleBool) {
      dispatch({
        type: 'UPDATE_EXAMPLE_STATE',
        update
      })
    }
  }

当您的操作依赖于API调用的提取结果时,在操作逻辑中使用异步/等待可以节省很多时间:

export const ExampleAction = () =>
  async (dispatch, getState) => {
    const { valueToCheck } = getState().ExampleReducer
        , result = await someAPICall(valueToCheck)
                   .catch(e => console.log(e))

    if (result.length > 0) {
      dispatch({
        type: 'UPDATE_EXAMPLE_STATE',
        update: result
      })
    }
  }

对于状态更新后组件的呈现行为取决于某些状态值的情况,我强烈建议reselect。一个非常基本的示例如下:

component.js

import React, { Component, Fragment } from 'react'
import { connect } from 'react-redux'
import { shouldDisplayItems } from '../selectors'
import MyListviewComponent from './myListview'

class ItemList extends Component {
  render() {
    const { shouldDisplayItems, items } = this.props

    return (
      <>
        {shouldDisplayItems && <MyListviewComponent items={items} />}
      </>
    )
  }
}

const mapStateToProps = ({ ListItems }) => shouldDisplayItems(ListItems)

export default connect(mapStateToProps)(ItemList)

selectors.js:

(假设您的ListItems简化程序具有参数itemsvisibilityFilter

import { createSelector } from 'reselect'

export const shouldDisplayItems = createSelector(
  [state => state],
  ({ items, visibilityFilter }) => {
    return {
      shouldDisplayItems: visibilityFilter && items.length > 0,
      items
    }
  }
)

我应该提到另一种选择是使用higher-order components,但是在掌握如何将过多的命令式逻辑保留在组件之外之前,使用此方法可能会很棘手(我很难学方式)。