无法更新我的应用程序的状态,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
玩 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 的警报,它显示正确的输出,即数组 'item' 内部的正确对象已更改,但不知何故未反映在 UI 和 rect 开发人员工具中。
//减速器
const DEFAULT_STATE = {
购物车数据:购物车数据
}
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
如果您更改状态的一部分,则需要为您的状态创建一个新的对象引用。按照你这样做的方式,你的旧状态仍然会 ===
你的新状态,所以 redux 无法知道它发生了变化。
此外,您的 setStatusToReserved
函数根本 return 没有任何作用!
你的状态不应该像现在这样嵌套得很深,我认为还有更多工作要做,但向前迈出的一步是这样的:
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,它是免费的并且解决了所有这些问题。
我大大简化了 reducer,我只是从商店获取我想要更改的状态(通过设置初始状态),并将产品列表作为我的智能组件(因为这是我唯一想要的状态改变)。我认为我对 reducer 所做的更改和仔细挑选我的智能组件有所帮助。感谢视频推荐,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,
}),
玩 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 的警报,它显示正确的输出,即数组 'item' 内部的正确对象已更改,但不知何故未反映在 UI 和 rect 开发人员工具中。
//减速器 const DEFAULT_STATE = { 购物车数据:购物车数据 }
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
如果您更改状态的一部分,则需要为您的状态创建一个新的对象引用。按照你这样做的方式,你的旧状态仍然会 ===
你的新状态,所以 redux 无法知道它发生了变化。
此外,您的 setStatusToReserved
函数根本 return 没有任何作用!
你的状态不应该像现在这样嵌套得很深,我认为还有更多工作要做,但向前迈出的一步是这样的:
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,它是免费的并且解决了所有这些问题。
我大大简化了 reducer,我只是从商店获取我想要更改的状态(通过设置初始状态),并将产品列表作为我的智能组件(因为这是我唯一想要的状态改变)。我认为我对 reducer 所做的更改和仔细挑选我的智能组件有所帮助。感谢视频推荐,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,
}),