Слушайте изменение состояния редуктора в компоненте в redux saga

Я использую redux-saga в своем приложении для реагирования. Мне нужно получить список заказов и отобразить его в компоненте. Для этого я создал экшены, редукторы и сагу.

Я попадаю в API в саге и

сага

import { call, put } from "redux-saga/effects";
import { path } from "ramda";
import OrdersActions from "../Redux/OrdersRedux";
export function* getOrders(api, action) {
  const { header } = action;
  console.log("order header", action);
  // make the call to the api
  const response = yield call(api.getOrders, header);
  console.log(response);
  if (response.ok) {
    yield put(OrdersActions.success(response.data));
    // do data conversion here if needed
  } else {
    yield put(OrdersActions.failure());
  }
}

редуктор

import { createReducer, createActions } from 'reduxsauce'
import Immutable from 'seamless-immutable'

/* ------------- Types and Action Creators ------------- */

const { Types, Creators } = createActions({
  getOrders: ['header'],
  success: ["data"],
  failure: [],
})

export const OrderTypes = Types
export default Creators

/* ------------- Initial State ------------- */

export const INITIAL_STATE = Immutable({
  new_orders: [],
  fetching: null,
  error: null,
})

/* ------------- Reducers ------------- */

// request the avatar for a user

export const getOrdersRequest = (state) =>
  state.merge({ fetching: true })

// successful avatar lookup
export const success = (state, action) => {
  const { data } = action;
  return state.merge({ fetching: false, error: null, new_orders: data.data.new_orders })
}

// failed to get the avatar
export const failure = (state) =>
  state.merge({ fetching: false, error: true })


/* ------------- Hookup Reducers To Types ------------- */

export const reducer = createReducer(INITIAL_STATE, {
  [Types.GET_ORDERS]: getOrdersRequest,
  [Types.SUCCESS]: success,
  [Types.failure]: failure,
})

MyComponent.js

class OrdersScreen extends Component {
  static navigationOptions = getHeaderStyle("Orders");

  constructor(props) {
    super(props);
    this.state = {
      new_orders: this.props.order_details.new_orders
    }
  }


  componentWillMount() {
    this.props.getOrders(this.getHeader());
  }


  componentWillReceiveProps(newProps, props) {
    if (newProps.order_details.new_orders.length > 0) {
      this.setState({
        new_orders: newProps.order_details.new_orders
      })
    }
  }

  render() {
    return (
      <View style={{ flex: 1, flexDirection: 'column', justifyContent: "flex-start" }}>
        <View style={{ padding: 10, flexDirection: 'row' }}>
          <Text style={{ flex: 3 }}>Order</Text>
        </View >
        {
            this.state.new_orders.map((item)=>{
                return<div>{item.order_id}</div>
            })
        }
        <View>
          <Button label="Make Payment" onPress={this.onMakePaymentClick()} />
        </View >
      </View>
    )
  }

  getHeader() {
    const { session_id } = this.props;
    return { "x-session-id": session_id };
  }

  onMakePaymentClick = () => {
    this.props.submitOrders();
  }
}


const mapStateToProps = (state, ownProps) => {
  return {
    order_details: state.order_details,
  }
}



const mapDispatchToProps = (dispatch) => ({
  getOrders: (header) => dispatch(OrdersActions.getOrders(header)),
})

export default connect(mapStateToProps, mapDispatchToProps)(OrdersScreen)

Мой вопрос, есть ли другой способ узнать, что значение a изменено в магазине, и получить измененное значение?

Я использую метод componentWillReceiveProps для любых новых изменений в магазине.

Теперь я хочу отправить другое действие «MakePayment» и нажать другой api, и если ответ в порядке, я хочу изменить экран, иначе отображается сообщение об ошибке.

Как видите, я устанавливаю new_orders в состояние в componentWillReceiveProps. Если я отправлю действие «MakePayment», оно снова вызовет componentWillReceiveProps, и заказы будут повторно обработаны.

Как этого избежать? И есть ли какой-либо другой компонент, который может отслеживать изменение в хранилище и значение, которое изменяется?


person John    schedule 22.09.2017    source источник
comment
вы можете установить, обновляются ли компоненты, с помощью shouldComponentUpdate   -  person bennygenel    schedule 22.09.2017
comment
я хочу обновить свой компонент только в том случае, если платеж прошел успешно или не прошел   -  person John    schedule 22.09.2017
comment
И более того, мне нужно добавить много условий в shouldComponentUpdate и componentWillReceiveProps. Мне нужно проверить несколько состояний и свойств. Это делает его сложным. Вместо этого, если был прослушиватель событий, который срабатывает при изменении определенного значения хранилища и дает измененное значение, это облегчит жизнь. Я прав ?   -  person John    schedule 22.09.2017


Ответы (1)


Во-первых, вы должны отправить свое действие из componentDidMount. Почему это объясняется в componentWillMount docs,

Во-вторых, вам не нужно использовать componentWillReceiveProps для получения изменений, потому что вы отправляете только getOrders один раз. Данные поступают прямо в вашу new_orders опору. В самом деле, поскольку вы просто заботитесь о new_orders, вы должны установить его напрямую как опору. Таким образом, ваш компонент будет наблюдать за изменениями в new_orders.

Наконец, если вы вызовете действие MAKE_PAYMENT, оно не приведет к повторному рендерингу, потому что платежные данные не будут находиться в ваших реквизитах или состоянии. Помните, что когда у вас есть данные в опоре, вам не нужно передавать их в состояние, если у вас нет действительно веской причины.

person Carlos C    schedule 28.12.2017