I am working to create a small contact app using React with ES6. I had some data displaying in the render function of a component - see the link to the question below for the original structure...
How to specify a key for React children when mapping over an array
However, because I was also putting a form on the same page and I needed to update my data in state, I had to move the data to a higher level component.
Now I'm having trouble traversing the components so that my original list of contacts shows up on the left. I had to remove most of what was in my render function on the contact-list component because it was completely breaking the build.
First, here is the address-book component with the form - this is working, both pulling in my initial 3 contacts from state, then concating new contacts from the form to the array. (Still need cleanup code here to make UI work right...)
import React from 'react';
import ContactList from './contact-list.jsx';
import ContactForm from './contact-form.jsx';
import ShortContact from './short-contact.jsx';
class AddressBook extends React.Component {
constructor() {
"use strict";
super();
this.state = {
showContacts: true,
contacts: [
{
id: 1,
fName: "aaa",
lName: "aaaaa",
imgUrl: "http://brainstorminonline.com/wp-content/uploads/2011/12/blah.jpg",
email: "aaa@aaaa.com",
phone: "999999999999"
},
{
id: 2,
fName: "bbbbb",
lName: "bbbbbbb",
imgUrl: "https://media.licdn.com/mpr/mpr/shrinknp_200_200/bbb.jpg",
email: "bbb@bbb-bbb.com",
phone: "888888888888"
},
{
id: 3,
fName: "Number",
lName: "Three",
imgUrl: "http://3.bp.blogspot.com/-iYgp2G1mD4o/TssPyGjJ4bI/AAAAAAAAGl0/UoweTTF1-3U/s1600/Number+3+Coloring+Pages+14.gif",
email: "three@ccccc.com",
phone: "333-333-3333"
}
];
};
}
render() {
"use strict";
return (
<div className="row address-book">
<div className="col-md-6">
<ContactList />
</div>
<div className="col-md-6">
<button className='btn' id="contact-submit-button" type="submit" value="Create Contact">Create New Contact </button>
<div>
<ContactForm addContact={this._addContact.bind(this)}/>
</div>
</div>
</div>
);
}
_addContact (fName, lName, company, email, phone, imgURL) {
"use strict";
const contact = {
id: this.state.contacts.length + 1,
fName,
lName,
company,
email,
phone,
imgURL
};
this.setState({ contacts: this.state.contacts.concat([contact]) });
}
_getContacts() {
"use strict";
return contactList.map((contact) => {
"use strict";
return (
<ShortContact contact={contact} key={contact.id}/>)
});
}
_getContactsTitle (contactCount) {
"use strict";
if(contactCount === 0) {
return 'No Contacts';
} else if (contactCount === 1) {
return '1 contact';
} else {
return `${contactCount} contacts`;
}
}
}
export default AddressBook;
However, the bottom 2 methods _getContacts and _getContactsTitle are the ones that are needed in my ContactForm component - which is this one:
import React from 'react';
import ShortContact from './short-contact.jsx';
class ContactList extends React.Component {
render() {
const contacts = this._getContacts();
return (
<div>
<h3>List of Contacts</h3>
<h4 className="contact-count">{this._getContactsTitle((contacts.length))}</h4>
<ul className="contact-list">
{contacts}
</ul>
</div>
);
}
}
export default ContactList;
The const that defines contacts as well as the <h4>
through the <ul>
is what breaks the app because as you can see it references the _getContactTitle method from the other component as well as {contacts} which is in the _getContacts method.
I'm guessing I need to do something like wrap them into functions and pass them - but I've gotten turned around and can't quite see how that would work here with React. Any help would be welcome. Thanks!