- Read Tutorial
- Watch Guide Video
Good job in the last video, where we set up the Redux DevTools.
First off, let's close out of our open code files for now. What we want to do is get access to our courses data, so it will display in our application instead of the dummy data we put in, and we can learn about that through the mapStateToProps
function.
Let's open up our library.js
file, and we're going to replace null
inside of it to mapStateToProps
. Then we'll declare the function with an argument of state
.
The state
that we're passing in is the exact same state that shows up in the DevTools. If we were to console.log state right now, with it returning state as well, we can see that we get the data in our console.
As you can see, it actually logged several times, and that's because we used componentDidMount
. I used this instead of componentWillMount
to show that in the component Lifecycle, our mapStateToProps
grabs the data to render it, but componentDidMount
then runs after the data's already been rendered, which causes it to repeat the data again. Let's change the componentDidMount
to componentWillMount
in library.js
.
This should give us access to the data we need. That data is being passed through the reducers into state. In this application, we only have the one type of action with data, but in a normal app, we may have several pieces of information coming in, so we want to make sure that we are only bringing in the course data. To do this, in library.js
we can stop logging the data, and we need to only be bringing in courses.
library.js
import React, { Component } from 'react'; import { connect } from 'react-redux'; import * as actions from '../../actions'; import LibraryCourse from './libraryCourse'; class Library extends Component { componentWillMount() { this.props.fetchCourses() } render() { return ( <div className="library"> <h1 className="library__title">Course Library</h1> <LibraryCourse/> <LibraryCourse/> <LibraryCourse/> </div> ) } } function mapStateToProps(state) { return { state.courses } } export default connect(mapStateToProps, actions)(Library);
Now that we have this being brought in, we can console.log our courses inside of our render function, so let's set our mapStateToProps
to return courses: state.courses
library.js
import React, { Component } from 'react'; import { connect } from 'react-redux'; import * as actions from '../../actions'; import LibraryCourse from './libraryCourse'; class Library extends Component { componentWillMount() { this.props.fetchCourses() } render() { console.log(this.props.courses); return ( <div className="library"> <h1 className="library__title">Course Library</h1> <LibraryCourse/> <LibraryCourse/> <LibraryCourse/> </div> ) } } function mapStateToProps(state) { return { courses: state.courses } } export default connect(mapStateToProps, actions)(Library);
Let's check our browser and see what we have.
It looks like we're getting just the course data, which is exactly what we wanted. Our next step is to now map over the course data that we have, and render it in our library. Let's work on it.
First, we can get rid of the console.log. Next we take where it says <LibraryCourse/>
and we can replace those calls with { this.renderCourses() }
. Now we have to build the renderCourses
function. Here is what it should look like:
library.js
import React, { Component } from 'react'; import { connect } from 'react-redux'; import * as actions from '../../actions'; import LibraryCourse from './libraryCourse'; class Library extends Component { componentWillMount() { this.props.fetchCourses() } renderCourses() { const data = this.props.courses return data.map(course => { return <LibraryCourse/> }) } render() { console.log(this.props.courses); return ( <div className="library"> <h1 className="library__title">Course Library</h1> { this.renderCourses() } </div> ) } } function mapStateToProps(state) { return { courses: state.courses } } export default connect(mapStateToProps, actions)(Library);
As you can see, we used the map
function go over the data that we have, and to put it where we need it. You should know how to use map
by now since going through the pre-work and the other projects, but if you still don't understand how it works, I recommend Googling it to learn about it.
As you also may have remembered from our last project that we need to assign a key to the courses, which would be correct. I just want to show you what happens when you don't assign a key. Let's check our browser.
It rendered out 10 objects, but you can see that they're all identical. Plus you can see that we have an error.
This comes from not having an key. The application is having rouble telling one course from the others. So let's put in a key on index. So we add key={index}
to our <LibraryCourse/>
, then we add it to our data.map.
library.js
import React, { Component } from 'react'; import { connect } from 'react-redux'; import * as actions from '../../actions'; import LibraryCourse from './libraryCourse'; class Library extends Component { componentWillMount() { this.props.fetchCourses() } renderCourses() { const data = this.props.courses return data.map((course, index) => { return <LibraryCourse key={index}/> }) } render() { console.log(this.props.courses); return ( <div className="library"> <h1 className="library__title">Course Library</h1> { this.renderCourses() } </div> ) } } function mapStateToProps(state) { return { courses: state.courses } } export default connect(mapStateToProps, actions)(Library);
With that done, I'm going to go ahead and end the video here, and in the next video we'll keep working on rendering our data in our libraryCourse.js
component.
Let's commit our code.
git status git add . git commit -m "implemented mapStateToProps and mapped over data to return the amount of course component instances we require" git push