React-native и Redux здоровый способ вызывать действия по смене реквизита - PullRequest
0 голосов
/ 02 октября 2018

Я уже некоторое время использую реагирующее с редуксом, и способ, которым я учусь вызывать действия, когда что-то меняется на пропе, использует 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);
    }
}

Мне нужен здоровый способ называть свои действия при смене реквизита.

Редактировать: Здесь у меня есть полная Сцена предложения и пример файла действия:

Сцена предложения: https://gist.github.com/macanhajc/0ac98bbd2974d2f6fac96d9e30fd0642

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

Ответы [ 2 ]

0 голосов
/ 28 ноября 2018

Как уже упоминалось в другом ответе, componentWillReceiveProps постепенно сокращается, поэтому я постараюсь устранить его там, где это возможно.Вы будете заботиться о своем коде на будущее и будете делать логику компонентов более декларативной и легко рассуждаемой.Как кто-то, кто был ответственен (и был разочарован) злоупотреблением методом жизненного цикла, как это, вот несколько вещей, которые мне помогли.

Помните, что при использовании redux-thunk наряду с передачей dispatch в качествеПервый аргумент, вы также можете передать getState в качестве второго.Это позволяет вам получать доступ к значениям состояния в логике действий, а не вносить их в подпорки вашего компонента и добавлять беспорядок.Что-то вроде:

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

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

Использование async / await в логике действий может быть спасением, когда ваше действие зависит от извлеченных результатов из вызова 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
      })
    }
  }

Для случаев, когда рендеринг вашего компонентаповедение зависит от определенных значений состояния после того, как ваше состояние было обновлено, я настоятельно рекомендую повторно выбрать .Очень простой пример будет выглядеть примерно так:

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 имеет параметры items и visibilityFilter)

import { createSelector } from 'reselect'

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

Я должен упомянуть, что другой вариант будет использовать компоненты высшего порядка , но это может быть сложноИспользуйте этот подход, прежде чем иметь представление о том, как сохранить слишком много императивной логики в ваших компонентах (я усвоил это нелегко).

0 голосов
/ 28 ноября 2018

Я согласен с @AnuragChutani и @Goldy с точки зрения ясности кода;разбейте его еще на несколько компонентов или функций.

Теперь, после некоторой проверки вашей функции componentWillReceiveProps, она определенно не достаточно конкретна, чтобы точно определить, какие именно изменения в реквизите.Если какая-либо подключенная переменная-редуктор изменится, функция componentWillReceiveProps будет вызываться каждый раз.

Так, например, если обновляется 'token' или 'selected_product', будет запускаться componentWillReceiveProps, даже если вы не хотели, чтобы он вызывался для токена.updates.

Вы можете использовать сравнение для конкретной переменной update в подпорках.Например, используя lodash

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

Во-вторых, вы можете вызывать действия / обратные вызовы в своих действиях, чтобы сузить навигацию.Например,

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