简体   繁体   English

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

[英]Unable to update the state of my app, console.log inside reducer shows that object has changed, but the state remains same

Playing with redux has got me very confusing.玩 redux 让我很困惑。 Some how its getting so difficult to update the state of just one key in object.一些如何更新对象中仅一个键的状态变得如此困难的原因。

A action is dispatched when user checks the checkbox inside of the component.当用户选中组件内的复选框时,将分派一个操作。 When it is checked the status of the product should change from NEW to RESERVED:当它被检查时,产品的状态应该从 NEW 变为 RESERVED:

// ProductRow.js // 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>
    )
  }
})

The parent component of ProductRow is ProductList: 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>
    )
  }
})

When the checkbox is ticked i get the alerted by console.log inside of reducer and its shows the right output that is the right object inside of the array 'item' has changed, but somehow it is not reflected in the UI and rect developer tools.当复选框被勾选时,我会收到 reducer 内部的 console.log 警报,它显示了正确的输出,即数组“item”中的正确对象已更改,但不知何故它没有反映在 UI 和 rect 开发人员工具中.

//Reducer const DEFAULT_STATE = { shoppingCartData: shoppingCartData } //Reducer 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

If you change a part of your state, you need to create a new object reference for your state.如果更改状态的一部分,则需要为状态创建新的对象引用。 With the way you're doing it, your old state will still === your new state, so there's no way for redux to know it changed.按照您的方式,您的旧状态仍将===新状态,因此 redux 无法知道它已更改。

Additionally, your setStatusToReserved function doesn't return anything at all!此外,您的setStatusToReserved函数根本不返回任何内容!

Your state shouldn't be as deeply nested as it is, and I think there's more work to be done, but a step forward is something like:你的状态不应该像现在这样嵌套很深,我认为还有更多的工作要做,但向前迈出的一步是:

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

I would highly suggest watching the Egghead Redux series which is free and addresses all of these problems.我强烈建议观看免费并解决所有这些问题的Egghead Redux 系列

I simplified the reducer much, and I am only getting the state from the store (by setting the initial state) that I want to change and made Product List my smart component(as that is the only one I want the state to be changed).我大大简化了减速器,我只从商店获取状态(通过设置初始状态),我想更改并将产品列表设为我的智能组件(因为这是我唯一想要更改状态的组件) . I think the change I made to reducer and picking up my smart component carefully helped.我认为我对 reducer 所做的更改和仔细挑选了我的智能组件有所帮助。 Thanks for the video recommendation, Dan's videos helped a lot.感谢视频推荐,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
[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,
    }),

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM