我正在使用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)
AddContactsComponent:
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
数组中添加了一个额外的联系人。有什么想法我的实现有什么问题吗?任何帮助表示赞赏!
答案 0 :(得分:1)
问题在于您如何分配initialState。由于您将CombineReducers与一键用作联系人,因此您的contactReducers会得到
[
{
"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;
}
}
做出上述更改后,一切都会正常
答案 1 :(得分:0)
您应该这样更改状态
export default function (state = { contacts : [] }, action) {
switch (action.type) {
case 'ADD_CONTACT':
console.log(state);
return {
...state,
contacts: [...state.contacts, ...contacts]
}
default:
return state;
}
}