In this lesson, we build an accordion component (similar to Chrome's native
<summary> elements) with React. We walk through setting up the component render function, props, state, propType validation, and adding conditional inline styling based on the state (if the accordion details are active or not). All done in ES6.
First, let's import React with Import, React from React. Then we will import a component that we'll be building that we have not yet created. Let's call that Accordion, and we'll put that inside of the Components folder, and then let's create its own folder, in case we want to add to it later, and then the Accordion.js file inside of that.
Next, I found it helpful to use our component as if it's already been built and to think about the type of API that we want, before we get into the actual Accordion.js file. Let's say React.render, and we'll use our Accordion component that hasn't been built yet. When we use that, we're going to want to be able pass in some props.
The two things we're going to need is some sort of summary. It's an element that we can select, and it will open up some details. We'll have a summary and some sort of text here, just a string, and then we're going to want to have details, as well. We'll just have that be a string right now.
Since our details are pretty long, let's pull this out, just to keep it clean. I'm going to create a new object called Data, and this will serve as a placeholder for any service data that we got in the future. We'll just have some hard-coded data here for now.
I'm going to have a summary property, which...let's just grab this value right here, and we'll use that by saying data.summary here, and then we'll grab our details string. I'll cut that, and I'll place it in a details property here, in our data object. Now we can use that in our prop by saying data.details.
Lastly, let's tell this component where to render, where to mount itself in the DOM. We'll say Document.getElementById. I have an element in my index HTML page that's called App, so we'll have it mount on that node.
Now that we know how our component is going to work, how we want it to work, let's create the actual component file, this guy right here. Let's go into our components directory, and we'll create a new Accordion folder, and then, inside of that folder, let's create a Accordion.js file.
Now let's open up that file we created, Accordion.js, and let's import React from React, and then we'll create a class called Accordion, which extends react.component. Inside of that class, let's create our render method. We'll have it return a paragraph that just says, "Hello world," for now. Let's make sure that it's actually working.
To be able to use this, we need to export the Accordion class as the default for this file, so that no, inside of our Index.js, when we made this important statement, this says "Import Accordion," we'll be able to get this Accordion class that's been exported from this Accordion file.
All right, we've got Hello World rendering in the browser. Let's go back now and actually use the props that we passed in our Index.js file. When we call Accordion, we're passing in Summary and Details as props, so let's use those in our Accordion.js file.
I'm going to do that by...let's create a new wrapping element for what we're going to render. We'll make this a section element. Then, inside of that, let's create an anchor tag, which will serve as the link for the summary text. Let's make that an anchor tag.
Then, inside of that, I'm going to say this.props.summary. Now let's add the details. I'll make that a paragraph, and I'll say this.props.details. We can see that our summary and details have been rendered out to the browser.
Let's make sure that those props are correct when they come in with the component, so we're going to create some prop types. Say Accordion.propTypes, and we are going to tell it that the summary prop should be React.propTypes -- this is going to be a strong, and it is required -- so isRequired. Then, for the details, it will be the same thing, a string, and it will also be required.
Now that we've validated our props that are coming in, and we have them rendering in the browser, we want to add the interaction for the component. What we're going for is when we click on a Lorum Ipsum anchor tag that as the summary prop in it, we want the details section to toggle to hide and show itself.
To do that, we're going to need to use State. Now let's create a constructor for our class, and we'll call Super, and then we'll say this.State, and set the initial property for the details view. Let's call that Active, and we'll set it to false by default, so that the details will be hidden, by default.
Now let's create some styles for showing and hiding. We'll say cont styles, and we'll create a style object, and then we'll create an active object, which sets the display to inherit. Then we'll create an inactive style object, which sets the display to None.
To make sure that's working, on our details paragraph, we'll set the style to be our styles object. We'll use inactive, and it should hide our details. We can see that our details have been hidden, so our inline styles are working, but we want people to toggle them.
Let's pull this out and create a new variable that we'll call state.style, and let's initialize that up here. We'll say const state style, and we'll set that equal to a ternary expression that says that if the state is active, we'll use the active styles, and if not, we'll use the inactive styles.
Next we want the accordion to toggle when we select the anchor element, so let's an onClick event, a function that we need to create called Toggle. Let's go up and create that now. We'll say Toggle and inside of toggle we're going to say this.setState, and we'll pass that an object, and the object is going to change Active to the opposite of what it was before.
Now we're almost done with our Accordion, but we're having a problem, because when we're trying to use this, in certain situations, it's not being bound to the scope we would expect from the ES5 React.createClass. Now that we're using ECMAScript 6, we're using actual ES6 classes, we have to manually bind the methods that we're using.
I'm going to say, up in my constructor, this.toggle, and we'll that's set to this.toggle, and we'll bind it to this. Now let's go back to our browser and check. We can click and toggle on and off the details.