无法更新我的应用程序的状态,reducer中的console.log显示该对象已更改,但状态保持不变

时间:2017-03-21 20:28:02

标签: reactjs redux react-redux

使用redux让我非常困惑。有些人如何很难更新对象中只有一个键的状态。

当用户选中组件内部的复选框时,将调度操作。检查时,产品的状态应从NEW更改为RESERVED:

// ProductRow.js

const ProductRow = React.createClass({
  propTypes: {
    item: PropTypes.object.isRequired,
    onChange: PropTypes.func.isRequired
  },

  render () {
    const { code, name, imageUrl, description } = this.props.item.product
    const {status} = this.props.item
    const {onChange} = this.props
    return (
      <div>
        <label htmlFor={code}>
          <input type='checkbox' id={code} onClick={onChange} value={status} />
          <img src={imageUrl} />
          <div className='name'>{name}</div>
          <div className='description'>{description}</div>
        </label>
      </div>
    )
  }
})

ProductRow的父组件是ProductList:

const ProductList = React.createClass({

  propTypes: {
    items: PropTypes.array.isRequired,
    dispatchSetStatusToReservedForItem: PropTypes.func
  },

  handleProductCheckBoxClick (item) {
    if (document.getElementById(item.product.code).checked) {
      this.props.dispatchSetStatusToReservedForItem(item)
    }
  },

  render () {
    const {items} = this.props
    return (
      <div>
        {
          items.map((item) => {
            return (
              <ProductRow key={item.id} onChange={this.handleProductCheckBoxClick.bind(this, item)} item={item} />
            )
          })
        }
      </div>
    )
  }
})

勾选复选框时,我会在reducer内部的console.log中收到警报,并显示正确的输出,该输出是数组中的正确对象&#39; item&#39;已经改变了,但不知何故它没有反映在UI和rect开发人员工具中。

//减速     const DEFAULT_STATE = {       shoppingCartData:shoppingCartData     }

const setStatusToReserved = (state, action) => {
  const {items} = state.shoppingCartData.data

  items.map(item => {
    if(action.item.id === item.id) {
      console.log(Object.assign({},action.item, {status: 'RESERVED'}))
      return Object.assign({}, action.item, {status: 'RESERVED'})
    }
  })
}

const rootReducer = (state = DEFAULT_STATE, action) => {
  switch (action.type) {

    case ACTIONS.SET_STATUS_TO_RESERVED:
      return setStatusToReserved(state, action)

    default:
      return DEFAULT_STATE
  }
}

export default rootReducer

3 个答案:

答案 0 :(得分:1)

如果更改了州的一部分,则需要为州创建新的对象参考。按照你的方式,你的旧状态仍然会===你的新状态,所以redux无法知道它已经改变了。

此外,您的setStatusToReserved功能根本不会返回任何内容!

你的国家不应该像现在这样深入嵌套,我认为还有更多的工作要做,但向前迈出的一步是:

const setStatusToReserved = (state, action) => {
  const {items} = state.shoppingCartData.data

  const newItems = items.map(item => {
    if(action.item.id === item.id) {
      console.log(Object.assign({},action.item, {status: 'RESERVED'}))
      return Object.assign({}, action.item, {status: 'RESERVED'})
    }
  })

  return {
    ...state,
    shoppingCartData: {
      ...shoppingCartData.data,
      items: newItems
    }
  }
}

我强烈建议您观看免费的Egghead Redux series并解决所有这些问题。

答案 1 :(得分:0)

我简化了reducer,我只是从商店获得状态(通过设置初始状态)我想要更改并使Product List成为我的智能组件(因为那是我唯一想要状态的被改变了)。我认为我对减速器和拾取我的智能组件所做的改变有所帮助。感谢视频推荐,Dan的视频帮了很大忙。

import { ACTIONS } from './actions'

/**
 * Returns an updated array with check product status set to RESERVED
 * @param state
 * @param action
 * @return {[*,*,*]}
 */
const setStatusToReserved = (state, action) => {
  let updateStatus = Object.assign({}, action.item, {status: 'RESERVED'})
  let index = state.indexOf(action.item)

  return [...state.slice(0, index), updateStatus, ...state.slice(index + 1)]
}

/**
 * Returns an updated array with check product status set to NEW
 * @param state
 * @param action
 * @return {[*,*,*]}
 */
const setStatusToNew = (state, action) => {
  let updateStatus = Object.assign({}, action.item, {status: 'NEW'})
  let index = state.indexOf(action.item)

  return [...state.slice(0, index), updateStatus, ...state.slice(index + 1)]
}

/**
 * Function that takes the current state and action and return new state
 * Initial state is set to product items
 * @param state
 * @param action
 * @return {{}}
 */
const rootReducer = (state = {}, action) => {
  switch (action.type) {
    case ACTIONS.SET_STATUS_TO_RESERVED:
      return setStatusToReserved(state, action)

    case ACTIONS.SET_STATUS_TO_NEW:
      return setStatusToNew(state, action)

    default:
      return state
  }
}

export default rootReducer

答案 2 :(得分:0)

[PROD_FORM_DETAILS_SUCCESS]: (state, { payload: { ProdDetailsData } }) => 
        {
            console.log(" reducer ===================== " , catalogueProductDetailsData);
        return {
      ...state,
      catalogueProductDetailsData,
      isFetching: false,
    }},

[CREATE_USER_FORM]: (state, {}) => {
      console.log(" reducer =======CREATE_USER_FORM ============== ");
      return {
        ...state,
        isFetching: false,
      };
    },

   //Without console

    [CREATE_USER_FORM]: (state, {}) => ({
      ...state,
      isFetching: true,
    }),