Redux 状态未在 reducer 中按预期构建
Posted
技术标签:
【中文标题】Redux 状态未在 reducer 中按预期构建【英文标题】:Redux state not getting built as expected in reducers 【发布时间】:2019-05-24 10:27:03 【问题描述】:我正在使用 React 和 Redux 构建一个简单的联系人应用程序。我的状态对象如下所示:
"contacts": [
"name": "Miguel Camilo",
"phone": "123456789"
,
"name": "Peter",
"phone": "883292300348"
,
"name": "Jessica",
"phone": "8743847638473"
,
"name": "Michael",
"phone": "0988765553"
],
"activeContact":
"name": "Peter",
"phone": "883292300348"
我正在尝试构建一个添加联系人功能,该功能将从页面上的输入中获取姓名和号码,并将它们添加到该州的 contacts
数组中。它是这样构建的:
ContactsList 组件:
class ContactList extends Component
renderList()
return this.props.contacts.map((contact) =>
return (
<li
key=contact.phone
onClick=() => this.props.selectContact(contact)
className='list-group-item'>contact.name</li>
);
);
render()
return (
<ul className = 'list-group col-sm-4'>
this.renderList()
</ul>
);
function mapStateToProps(state)
return
contacts: state.contacts
;
function mapDispatchToProps(dispatch)
return bindActionCreators( selectContact: selectContact , dispatch);
export default connect(mapStateToProps, mapDispatchToProps)(ContactList)
添加联系人组件:
class AddContactModal extends Component
constructor()
super();
this.state = firstName: "", phone: "";
handleNameChange(event)
this.setState(firstName: event.target.value)
handlePhoneChange(event)
this.setState(phone: event.target.value);
render()
return(
<div>
<input type="text" className="name" placeholder="Contact Name" onChange=(event) => this.handleNameChange(event)/>
<input type="text" className="phone" placeholder="Contact Phone" onChange=(event) => this.handlePhoneChange(event)/>
<AddContactButton firstName=this.state.firstName firstName=this.state.phone onClick=() => this.props.addContact("name": this.state.firstName, "phone": this.state.phone)/>
</div>
);
function mapStateToProps(state)
console.log('mapstatetoprops:');
console.log(state);
return
contacts: state.contacts
;
function mapDispatchToProps(dispatch)
return bindActionCreators( addContact: addContact , dispatch);
export default connect(mapStateToProps, mapDispatchToProps)(AddContactModal)
Contacts Reducer(包含 ADD_CONTACT 处理程序):
export default function (state = contacts : [] , action)
switch (action.type)
case 'ADD_CONTACT':
console.log(state);
return Object.assign(, state,
contacts: state.concat([
name: action.payload.name,
phone: action.payload.phone
])
)
default:
return state;
应用的 index.js 建立商店的地方:
const createStoreWithMiddleware = applyMiddleware()(createStore);
const initialState =
"contacts": [
"name": "Miguel Camilo",
"phone": "123456789"
,
"name": "Peter",
"phone": "883292300348"
,
"name": "Jessica",
"phone": "8743847638473"
,
"name": "Michael",
"phone": "0988765553"
],
"activeContact": null
;
ReactDOM.render(
<Provider store= createStoreWithMiddleware(reducers, initialState) >
<App />
</Provider>
, document.querySelector('.container'));
并结合我的减速器:
const rootReducer = combineReducers(
contacts: ContactsReducer,
activeContact: ActiveContactReducer
);
export default rootReducer;
我的问题是,当我单击“添加联系人”按钮时,一个新的 contacts
数组被添加到该状态的现有 contacts
数组中,然后出于某种奇怪的原因,我的初始联系人列表被添加到国家。因此,当我登录this.props.contacts
时,单击添加联系人按钮后(在出错之前),它看起来如下所示:
"0":
"name": "Miguel Camilo",
"phone": "123456789"
,
"1":
"name": "Peter",
"phone": "883292300348"
,
"2":
"name": "Jessica",
"phone": "8743847638473"
,
"3":
"name": "Michael",
"phone": "0988765553"
,
"contacts": [
"name": "Miguel Camilo",
"phone": "123456789"
,
"name": "Peter",
"phone": "883292300348"
,
"name": "Jessica",
"phone": "8743847638473"
,
"name": "Michael",
"phone": "0988765553"
,
"name": "123",
"phone": "123"
]
因此,在包含原始值和新值的原始 contacts
数组中添加了一个新的 contacts
数组。而原来的contacts
数组保持不变。
我不确定这是为什么。最初我认为传递给我的 reducer 的 state
对象是完整状态,但它似乎只是我状态的 contacts
部分,所以我修改了我的 Object.assign() 调用以通过更改它来解决这个问题从 contacts: state.contacts.concat()
到 contacts: state.concat()
但这仍然没有解决问题。
我希望返回到我的 ContactsList 组件的状态如下所示:
"contacts": [
"name": "Miguel Camilo",
"phone": "123456789"
,
"name": "Peter",
"phone": "883292300348"
,
"name": "Jessica",
"phone": "8743847638473"
,
"name": "Michael",
"phone": "0988765553"
,
"name": "this is the new contact",
"phone": "123"
],
"activeContact":
"name": "Peter",
"phone": "883292300348"
只是在我的contacts
数组中添加了一个额外联系人的原始状态。任何想法我的实施有什么问题?任何帮助表示赞赏!
【问题讨论】:
你是否使用 combineReducers,如果使用也请添加该部分 @ShubhamKhatri 添加了 【参考方案1】:问题在于如何分配初始状态。由于您使用 combineReducers 的一个键是联系人,因此您的 contactsReducers 得到
[
"name": "Miguel Camilo",
"phone": "123456789"
,
"name": "Peter",
"phone": "883292300348"
,
"name": "Jessica",
"phone": "8743847638473"
,
"name": "Michael",
"phone": "0988765553"
],
如你所愿
contacts: [
"name": "Miguel Camilo",
"phone": "123456789"
,
"name": "Peter",
"phone": "883292300348"
,
"name": "Jessica",
"phone": "8743847638473"
,
"name": "Michael",
"phone": "0988765553"
]
所以你需要做的改变是
export default function (state = [], action)
switch (action.type)
case 'ADD_CONTACT':
console.log(state);
return state.concat([
name: action.payload.name,
phone: action.payload.phone
])
default:
return state;
进行上述更改后,一切都会奏效
【讨论】:
这确实有效!太感谢了。虽然状态不应该是不可变的,reducer 不应该只返回一个副本吗?state.concat
是否返回一个新对象而不是一个变异的 state
?
concat 返回一个新数组并且不会改变原来的数组【参考方案2】:
你应该像这样改变你的状态
export default function (state = contacts : [] , action)
switch (action.type)
case 'ADD_CONTACT':
console.log(state);
return
...state,
contacts: [...state.contacts, ...contacts]
default:
return state;
【讨论】:
以上是关于Redux 状态未在 reducer 中按预期构建的主要内容,如果未能解决你的问题,请参考以下文章
Redux 状态未在开发工具中更新,但当前状态正在反映在道具中
Redux:Reducer 需要其他 Reducer 的状态?