JS-201-ReactFundamentals
  • Part 0: App Overview
  • Part 1: Intro to React
    • 1.0: Packages Setup
    • 1.1: Project Setup
    • 1.2: React Router Dom
  • Part 2: JavaScript Concepts
    • 2.0: ES6 Overview
    • 2.1: classes
    • 2.2: constructors
    • 2.3: extends
    • 2.4: super
    • 2.5: interpolation
    • 2.6: map
    • 2.7: filter
  • Part 3: Functional Components
    • 3.0: Functional Components Overview
    • 3.1: Calling Functional Components
    • 3.2: Single Element Rule
    • 3.3: Arrow Functions
    • 3.4: Challenge
    • 3.4: Solution
    • 3.5: Challenge 2
    • 3.5: Solution 2
  • Part 4: JSX Challenge
    • 4.1: JSX Overview
    • 4.1: Challenge Answer
    • 4.2: className
  • Part 5: Class Concepts
    • 5.1: State
    • 5.2: setState
    • 5.3: Class Components Challenge
    • 5.4: Class Components Challenge Answer
  • Part 6: Props Starter
    • 6.0: Props Overview
    • 6.1: Props Demo and Challenge 1
    • 6.2: Props Answer 2
    • 6.3: Props Passing Functions and Challenge 2
    • 6.4: Props Answer 2
    • 6.5: External Props and Mapping Components
    • 6.6: PropTypes
  • Part 7: Lifecycle Methods
    • 7.0: Lifecycle Overview
    • 7.1: Lifecycle Methods
    • 7.2: Mounting Methods
    • 7.3: Update Methods
    • 7.4: Unmount Methods
  • Part 8: Apps
    • 1.0 - Small Timer Apps
      • 1.1 - Simple Timer
      • 1.2 - Clock App
      • 1.3 - Stop Watch App
      • 1.4 - Challenge
    • 2.0 - Concept List
      • 2.1 - Concept Data
      • 2.2 - Concept App Component
      • 2.3 - Concept Component
      • 2.4 - Concept List Component
    • 3.0 - NYT
      • 3.1 - NytApp Component
      • 3.2 - Nyt Results
    • 4.0 - The Friend List App
      • 4.1 - Friend List App Component
      • 4.2 - Friend Component
    • 5.0 - Movie Search Application
      • 5.1 - Form Component
      • 5.2 - Form Results Component
      • 5.3 - Styled Components
    • 6.0 - YouTube Api
      • 6.1 - Video Component
      • 6.2 - Video Component
      • 6.3 - Video Component
    • 7.0 - Github Api Application
      • 7.1 - The Users
      • 7.2 - Github API Component
      • 7.3 - Github API Card
      • 7.4 - Github API Card Form
      • 7.5 - Github API Card List
      • 7.6 - Github API Search
      • 7.7 - Github API Challenge
    • 8.0 - Bitcoin Api Application
      • 8.1 - Bitcoin API Setup
      • 8.2 - Bitcoin API Fetch
      • 8.3 - Bitcoin API Line Chart
      • 8.4 - Bitcoin API Fetching Data
      • 8.5 - Bitcoin API Info Box
      • 8.6 - Bitcoin API Completed Code
    • 9.0 - Google Maps Api Challenge
    • 10.0 - Sound Cloud App Challenge
    • 11.0 - VR App Challenge
    • 12.0 - React Native Intro
  • Part 9: Project
  • Part 10: Notes
    • 10.1 - Resources
    • 10.2 - Troubleshooting
Powered by GitBook
On this page
  1. Part 6: Props Starter

6.5: External Props and Mapping Components

Frequently, props will be passed not directly from the parent to the child, but through an intermediate component. Props can be passed from ancestors to descendants through as many 'middleman' components as you need. Like with our discussion about information exchange between components on the last page, this is both a blessing and a curse. The benefit is that any component can draw upon methods or data from a component higher in the hierarchy, but the drawback is that it requires more props for this information to be passed.

Without building lots of components, we're going to simulate this grandparent-parent-child relationship being described. Let's add the below array of objects above the export default PropsDemo extends React.Component{ line in our code. The object represents the props we want to share with our FunctionalComp component, and PropsDemo is now the parent middleman to get this information to FunctionalComp. You can think of the object we're adding as coming from a higher ancestor component in the React hierarchy, or as from outside the React project altogether. Either way, we have more links in the chain of information passage from source of data to component using that data.

const propsFromOutside = [
    {string: 'Color Toggle', function: 'colorToggle'},
    {string: 'Background Color Toggle', function: 'backgroundColorToggle'},
    {string: 'Border Radius Toggle', function: 'borderRadiusToggle'},
    {string: 'Border Style Toggle', function: 'borderStyleToggle'}
]

Let's now change how prop values are defined inside the calls of each FunctionalComp instance within our render. We're going to move away from hard-coded values to using our array of objects to give us props values. This will feel a little wild, but we'll break down what's going on after you implement this code:

<FunctionalComp string={propsFromOutside[0].string} function={this[`${propsFromOutside[0].function}`]}/>
<FunctionalComp string={propsFromOutside[1].string} function={this[`${propsFromOutside[1].function}`]}/>
<FunctionalComp string={propsFromOutside[2].string} function={this[`${propsFromOutside[2].function}`]}/>
<FunctionalComp string={propsFromOutside[3].string} function={this[`${propsFromOutside[3].function}`]}/>

As you can see, all of our prop values now refer to the propsFromOutside array instead of the values we manually typed out. Each of our string props refers to an index number of our propsFromOutside array, giving us back one of the four objects in our array. The .string grabs hold of the value of the string key inside each of the 4 objects.

More complex perhaps is how we refer to the value of each function prop. Each function prop first refers to this. We know the this keyword lets us refer to whatever outter conext our code currently resides in. For instance, our FunctionalComp calls occur within our render() method, which is contained within our PropsDemo class component. In this sense, the render() method contains our inner context, and the PropsDemo class is the outter context holding our FunctionalComp calls. So in this case, this refers to our class component PropsDemo.

Next, we see square brackets after our use of this. As a refresher, the square brackets let us grab hold of the key from an object by inserting a string. In this case, we use string interpolation ${...} to refer to a variable string, whatever the function key is for each object. In essence, we can grab hold of any key our propsFromOutside array refers us to. Take a minute to check it out and begin to wrap your head around it before we streamline this code a bit.

One thing to begin to train your eye to look for is repeated code structure. When you see repeated code structure as you write, there's always a more elegant way to write out what you're doing. There are nuances to this statement, but we can begin to explore this topic by refactoring our FunctionalComp calls within our render method. Let's rebuild our calls as follows inside our render:

render(){
  const display = propsFromOutside.map((el, index) => {
    return(
        <FunctionalComp key={index} string={el.string} function={this[`${el.function}`]}/>
    )
  })
  return(
    <div className="main">
        <div className="mainDiv">
            <div style={this.state}>
                {display}
            </div>
        </div>
    </div>
  )
}

Let's talk about what's going on here. We've outsourced the job of calling each FunctionalComp to the display array. The display array maps each object inside of propsFromOutside to a FunctionalComp call, storing the string and function from that object as props inside the FunctionalComp. Notice that we've added key={index} to our component calls. If you take that out of your .map, you'll getting the following warning in your console:

Why does React care about a unique key for each call of FunctionalComp? Well, React is smart enough to 're-render' (re-display) to the page only the components which have changed props. So, for instance, if one of the FunctionalComp components has been referring to the colorToggle method, but it's now referring to the borderStyleToggle method, React will re-render that component, as the data tied to that component has changed. However, React won't be able to identify if props and internal information for a component has changed unless the component has some sort of name tied to it. Hence the use of key. By giving each component a key, React can now identify when a single instance of FunctionalComp has changed, and re-display just that component to the DOM, rather than re-rendering all of the FunctionalComp instances.

In our last view of props within this module, we're going to explore PropTypes.

Previous6.4: Props Answer 2Next6.6: PropTypes

Last updated 6 years ago

Missing Key Error