Skip to content

Commit

Permalink
Controlled Components
Browse files Browse the repository at this point in the history
  • Loading branch information
tupkung committed Sep 2, 2017
1 parent 97747de commit a4156b9
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 25 deletions.
6 changes: 4 additions & 2 deletions contacts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"escape-string-regexp": "^1.0.5",
"react": "^15.6.1",
"react-dom": "^15.6.1",
"react-scripts": "1.0.12"
"react-scripts": "1.0.12",
"sort-by": "^1.2.0"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
}
}
}
88 changes: 68 additions & 20 deletions contacts/src/ListContacts.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,76 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import escapeRegExp from 'escape-string-regexp'
import sortBy from 'sort-by'

const ListContacts = ({contacts, onDeleteContact}) =>
<ol className="contact-list">
{contacts.map( (contact) =>
<li key={contact.id} className='contact-list-item'>
<div className='contact-avatar' style={{
backgroundImage: `url(${contact.avatarURL})`
}}/>
<div className='contact-details'>
<p>{contact.name}</p>
<p>{contact.email}</p>
</div>
<button onClick={()=>onDeleteContact(contact)} className='contact-remove'>
Remove
</button>
</li>
)}
</ol>
class ListContacts extends Component {
static propTypes = {
contacts: PropTypes.array.isRequired,
onDeleteContact: PropTypes.func.isRequired
}

state = {
query: ''
}

updateQuery = (query) => {
this.setState({query: query.trim() })
}

clearQuery = () => {
this.setState({ query: ''})
}

render() {
const {contacts, onDeleteContact} = this.props
const {query} = this.state

ListContacts.propTypes = {
contacts: PropTypes.array.isRequired,
onDeleteContact: PropTypes.func.isRequired
let showingContacts
if (query) {
const match = new RegExp(escapeRegExp(query), 'i')
showingContacts = contacts.filter((contact)=>match.test(contact.name))
} else {
showingContacts = contacts
}

showingContacts.sort(sortBy('name'))

return (
<div className="list-contacts">
<div className="list-contacts-top">
<input
className="search-contacts"
type="text"
placeholder="Search contacts"
value={this.state.query}
onChange={(event) => this.updateQuery(event.target.value)}
/>
</div>
{showingContacts.length !== contacts.length && (
<div className='showing-contacts'>
<span>Now showing {showingContacts.length} of {contacts.length}</span>
<button onClick={this.clearQuery}>Show all</button>
</div>
)}
<ol className="contact-list">
{showingContacts.map( (contact) =>
<li key={contact.id} className='contact-list-item'>
<div className='contact-avatar' style={{
backgroundImage: `url(${contact.avatarURL})`
}}/>
<div className='contact-details'>
<p>{contact.name}</p>
<p>{contact.email}</p>
</div>
<button onClick={()=>onDeleteContact(contact)} className='contact-remove'>
Remove
</button>
</li>
)}
</ol>
</div>
)
}
}

export default ListContacts
2 changes: 1 addition & 1 deletion contacts/src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ body, .app {
font-size: 0;
}

.showing-contact {
.showing-contacts {
text-align: center;
margin: 20px 0;
}
Expand Down
14 changes: 12 additions & 2 deletions contacts/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4302,6 +4302,10 @@ object-keys@^1.0.8:
version "1.0.11"
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.11.tgz#c54601778ad560f1142ce0e01bcca8b56d13426d"

object-path@0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/object-path/-/object-path-0.6.0.tgz#b69a7d110937934f336ca561fd9be1ad7b7e0cb7"

object.omit@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa"
Expand Down Expand Up @@ -5055,7 +5059,7 @@ react-dev-utils@^4.0.0:
strip-ansi "3.0.1"
text-table "0.2.0"

react-dom@15.6.1, "react-dom@^15 || ^16":
"react-dom@^15 || ^16", react-dom@^15.6.1:
version "15.6.1"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-15.6.1.tgz#2cb0ed4191038e53c209eb3a79a23e2a4cf99470"
dependencies:
Expand Down Expand Up @@ -5119,7 +5123,7 @@ react-scripts@1.0.12:
optionalDependencies:
fsevents "1.1.2"

react@15.6.1, "react@^15 || ^16":
"react@^15 || ^16", react@^15.6.1:
version "15.6.1"
resolved "https://registry.yarnpkg.com/react/-/react-15.6.1.tgz#baa8434ec6780bde997cdc380b79cd33b96393df"
dependencies:
Expand Down Expand Up @@ -5616,6 +5620,12 @@ sockjs@0.3.18:
faye-websocket "^0.10.0"
uuid "^2.0.2"

sort-by@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/sort-by/-/sort-by-1.2.0.tgz#ed92bbff9fd2284b41f6503e38496607b225fe6f"
dependencies:
object-path "0.6.0"

sort-keys@^1.0.0:
version "1.1.2"
resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-1.1.2.tgz#441b6d4d346798f1b4e49e8920adfba0e543f9ad"
Expand Down

0 comments on commit a4156b9

Please sign in to comment.