Repository navigation
Set up Contact List
Now that we have our app wired up with Redux, we'll create a ContactList component that's going
to list all of the contacts registered to our app.
We're not going to set up database persistence yet.
Since our new component is stateful, meaning that it will have to listen to our Redux state to
fetch the contacts, we need to wire it to Redux somehow. react-redux makes it easy, however,
providing us with a connect function that wires up the state to our component by passing it
via props. This means that we're going to access the Redux state in our component via
this.props.
For the purposes of this guide, we're going to place our stateful components in a containers
folder and our presentational (stateless) components in a components folder.
mkdir src/containers
nano src/containers/ContactList.jsimport React, { Component } from 'react';
class ContactList extends Component {
render() {
}
}
export default ContactList;In order to make the app state available to our component, we need to wrap it with a function
call to connect, one of the functions available in the react-redux library. connect returns
a function, that we will immediately call passing as its argument our new component.
import React, { Component } from 'react';
import { connect } from 'react-redux';
class ContactList extends Component {
render() {
}
}
export default connect()(ContactList);This connect function will take two arguments: a function defining how the component will see
the state, and one defining how it will call the actions, or, more precisely, dispatch them to
the reducers. We will call these functions mapStateToProps and mapDispatchToProps, respectively.
Since we won't need to deal with dispatching actions yet, we will have mapDispatchToProps return
an empty object, but we will return to it later on. Let's implement our mapStateToProps function now.
import React, { Component } from 'react';
import { connect } from 'react-redux';
class ContactList extends Component {
render() {
}
}
const mapStateToProps = state => ({
...state.contacts
});
const mapDispatchToProps = dispatch => ({});
export default connect(mapStateToProps, mapDispatchToProps)(ContactList);Now our component has access to both contactList and loading keys through this.props.
Let's present something in our component, then. For now, we're not going to deal with the
loading prop yet.
import React, { Component } from 'react';
import { connect } from 'react-redux';
class ContactList extends Component {
render() {
return (
<div>
<h1>Contacts</h1>
<table className="table table-striped table-responsive">
<thead>
<tr>
<th>Name</th>
<th>Phone</th>
<th>Email</th>
</tr>
</thead>
<tbody>
{
this.props.contactList.map(({ name, phone, email }, index) => (
<tr key={index}>
<td>{name}</td>
<td>{phone}</td>
<td>{email}</td>
</tr>
))
}
</tbody>
</table>
</div>
);
}
}
const mapStateToProps = state => ({
...state.contacts
});
const mapDispatchToProps = dispatch => ({});
export default connect(mapStateToProps, mapDispatchToProps)(ContactList);When we're iterating over an array and we render multiple components as a result of that loop,
we need to include a key prop to the highest-order component being returned so React can keep
track of each component being rendered. Not including the key prop will raise an error.
Now let's render ContactList in our App component.
nano src/App.jsimport React, { Component } from 'react';
import logo from './logo.svg';
import ContactList from './containers/ContactList';
import './App.css';
class App extends Component {
render() {
return (
<div className="App">
<div className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h2>Contact List</h2>
</div>
<div className="App-intro">
<ContactList />
</div>
</div>
);
}
}
export default App;Since our contactList is still empty, this component won't show anything.
Commit the changes, then head to the next step.
git add .
git commit -m "Create ContactList component"Next step: Add Bootstrap
{ ...var } is object spreading notation from ES7 that means "associate all keys and values
to this new object". It's basically a shorthand to Object.assign({}, var).
This means that, in our mapStateToProps, we're returning a new object containing all the keys
and values from the state.contacts object. Reminding that the state argument passed to
mapStateToProps is the global application state.