Closed QuincyLarson closed 7 years ago
We would be covering React with ES6 construct, and we might be referring to create-react-app
for starting point of react projects. Is that correct?
I hope we are using
import { Component } from 'react'
export default AppContainer extends Component {
constructor(props) {
super(props);
// initialize state here
}
render() {
return (
)
}
}
syntax and not the React.createClass()
syntax?
edit: see first comment for list
Yes, we would not teach createClass. The FB team has marked this as legacy.
Challenge Text
React is a User Interface (UI) builder library. And every UI element in React can be described as a JSX
component
.JSX is a syntax that lets you define your React UI component using XML.
It's similar to HTML that you have already learned, however there are a few key differences, which we would learn about as we progress.
If we want to
render
adiv
component in React, we can simply refer to it as<div> </div>
, and put it insidereturn
statement of arender()
function.Instructions Render an
li
component, replacing thediv
component we are currently rendering, insiderender()
in theList
object. Don't forget to close yourli
tag, like we closed thediv
tag.Challenge Seed
import React, { Component } from 'react';
export default List extends Component {
constructor(props) {
super(props);
}
render() {
return (
// change code below this line
<div>
</div>
// change code above this line
)
}
}
Challenge Solution
import React, { Component } from 'react';
export default List extends Component {
constructor(props) {
super(props);
}
render() {
return (
// change code below this line
<li>
</li>
// change code above this line
)
}
}
Challenge Tests
/cc @BerkeleyTrue How are we planning to test these?
Challenge Text
We have already seen how JSX syntax can used to define a component.
Now, we would be using JSX to combine two or more component to create one component. This is known as
composition
.We want to create two lists inside an unordered list component.
We shall use the
List
component we built previously. We want to build aMainList
component with twoList
components.render() { return ( <ul> <List /> <List /> </ul> ) }
Notice the self-closing tag
/>
in the example when we are usingList
component via the<List>
tag. Also notice that thereturn
statement requires you to wrap multiple components inside a top-level component. In this case,<ul>
tag does the trick.Instructions You are given a search bar component
SearchBar
and aGroceryList
component. Compose them to render them together as one unit, and use<div>
tag as top level component that wraps these two. Make sure the search bar appears before the grocery list, just like most find-in-list UIs normally do.
Challenge Seed
import React, { Component } from 'react';
import SearchBar from './components/searchbar'
import GroceryList from './components/grocery-list'
export default AppContainer extends Component {
constructor(props) {
super(props);
}
render() {
return (
// change code below this line
// change code above this line
)
}
}
Challenge Solution
import React, { Component } from 'react';
import SearchBar from './components/searchbar'
import GroceryList from './components/grocery-list'
export default AppContainer extends Component {
constructor(props) {
super(props);
}
render() {
return (
// change code below this line
<div>
<SearchBar />
<GroceryList />
</div>
// change code above this line
)
}
}
Challenge Tests [ WIP ]
Challenge Text
We have been rendering JSX components with HTML-like tags, and composing multiple components into one big top-level component.
Next up is to style them right.
Just like in HTML, we would provide our component with a CSS class for styling. You can pass any
property
within a JSX component with the syntax<TagName property=<property> />
. Here, we are going to pass the propertyclassName
with a CSS class name.render() { return ( <div className="container"> <nav className="navbar"></nav> <div className="row"> <div className="col-xs-10 col-md-8 col-lg-6"> </div> </div> </div> ) }
The example is that of a typical Bootstrap page, if we were to build the UI with React. We cannot use
class
in place ofclassName
, because it is a reserved JS keyword in ES6.Instructions Give the button a CSS class
pill
Challenge Seed
import React, { Component } from 'react';
export default AppContainer extends Component {
constructor(props) {
super(props);
}
render() {
return (
// change code below this line
<div>
<button />
</div>
// change code above this line
)
}
}
Challenge Solution
import React, { Component } from 'react';
export default AppContainer extends Component {
constructor(props) {
super(props);
}
render() {
return (
// change code below this line
<div>
<button className="pill" />
</div>
// change code above this line
)
}
}
Challenge Tests [ WIP ]
Do we want to use classnames npm package here? /cc @BerkeleyTrue
Challenge Text
We have been getting familiar with JSX for quite a while now. But we are yet to take a look under the hood - how this JSX gets compiled into JS and generates the HTML for the UI
Next we are going to do just that!
The JSX compiler compiles the following JSX
render() { return ( <div className="container"> <nav className="navbar"></nav> <div className="row"> <div className="col-xs-10 col-md-8 col-lg-6"> </div> </div> </div> ) }
and generates the following pure JS code
render() { return ( React.createElement( "div", { className: "container" }, React.createElement("nav", { className: "navbar" }), React.createElement( "div", { className: "row" }, React.createElement("div", { className: "col-xs-10 col-md-8 col-lg-6" }) ) ); ) }
Looking at the generated JS code, it should be obvious how JSX makes it easy writing the same code, without having to go through the pain of nesting
React.createElement()
and closing parentheses right.It is to be kept in mind, that
React.createElement
is similar todocument.createElement
, but not same. We will get to the differences a bit later.
Instructions
Replace the generated code, and create an equivalent JSX formulation of the same
Challenge Seed
import React, { Component } from 'react';
export default AppContainer extends Component {
constructor(props) {
super(props);
}
render() {
return (
// change code below this line
React.createElement(
Form,
{ className: "form" },
React.createElement(
Row,
null,
React.createElement(Label, null),
React.createElement(Input, null)
)
);
// change code above this line
)
}
}
Challenge Solution
import React, { Component } from 'react';
export default AppContainer extends Component {
constructor(props) {
super(props);
}
render() {
return (
// change code below this line
<Form className="form">
<Row>
<Label />
<Input />
</Row>
</Form>
// change code above this line
)
}
}
Challenge Tests [ WIP ]
@alayek wow - much respect for getting off to such a fast start with these! I think @BerkeleyTrue is still mulling how we'll test these.
@BerkeleyTrue should we plan to use regex testing for the first presence of the JSX challenges and then use our usual Chai tests once we start rendering things? Or do you have a more elegant approach for this in mind?
Challenge Description
So, far we have been preparing ourselves with JSX syntax. And now we can render our components on the UI.
React provides in-built components, that resolve to common HTML tags.
To render a component, we have to use
ReactDOM
module and invoke therender
function.We would also need to provide a
target
, within which we have to render our component. Usually, this target can be the HTMLid
attribute of adiv
.We can render to HTML like this
ReactDOM.render( <div> <p> My Text Here </p> </div>, document.getElementById('app') ); We are assuming there is a `div` in our HTML with the id `app`.
Instructions
Render a
ul
with two list itemsli
, where the first item is1
, and second item contains the text2
. UseReactDOM.render()
and your target is thediv
withid
container
.
Challenge Seed
import ReactDOM from 'react-dom'
// change code below this line
ReactDOm.render(
<ul>
</ul>,
document.getElementById()
);
// change code above this line
Challenge Solution
import ReactDOM from 'react-dom'
// change code below this line
ReactDOM.render(
<ul>
<li>1</li>
<li>2</li>
</ul>,
document.getElementById('container')
);
// change code above this line
Challenge Tests [WIP]
Challenge Description
We now know how to compose JSX components to build new custom components. We have also learned how to use
ReactDOM.render()
to render existing React components to HTML so that browser can display it.We can also render our custom components exactly the same way, and React will render all the internal nested components the custom component is made of.
To render a custom component, we have to use
ReactDOM
module and invoke therender
function. In addition to this, we also use proper closing tags.We would also need to provide a
target
, within which we have to render our component. Usually, this target can be the HTMLid
attribute of adiv
.We can render to HTML like this
ReactDOM.render( <AwesomeComponent />, document.getElementById('app') ); We are assuming there is a `div` in our HTML with the id `app`. Notice how we closed the tag with `/>`
Instructions
Render a
AppContainer
component, which is made up ofGroceryList
andSearchBar
components that we earlier created. UseReactDOM.render()
and closing tags properly. Target adiv
with IDapp
Challenge Seed
import ReactDOM from 'react-dom'
import AppContainer from './components/AppContainer'
// change code below this line
ReactDOm.render(
<div></div>,
document.getElementById()
);
// change code above this line
Challenge Solution
import ReactDOM from 'react-dom'
import AppContainer from './components/AppContainer'
// change code below this line
ReactDOM.render(
<AppContainer />,
document.getElementById('container')
);
// change code above this line
Challenge Tests
Challenge Description
We have learned how to create and reder JSX components. Now, we shall add some dynamism to our components. This would increase re-usability of components, and we can pass dynamic data to our components.
Say, we want to display two names on the UI. A simple, naive way to go about this, is to create two separate components, each having the corresponding name hardcoded.
<Name_1 /> <Name_2 />
Instead, we should somehow build a single component that can display any name, and use that component to render as many names as we want.
This means we need to pass the name we want to display, to the component.
render( <Name display="No one" /> );
The name
display
is entirely arbitrary, as long as the component internally understands what that property means.The property
display
of the component should be used in creating the component. You can access the propertypropName
asthis.props.propName
inside the component definition.
Instructions
Make the
Name
component work properly to display the name using<Name display="No one" />
, passed to it as propertydisplay
. Use thethis.props
syntax.
Challenge Seed
import { Component } from 'react';
export default Name extends Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
{/* Change code below this line */}
<h1> </h1>
{/* Change code above this line */}
</div>
)
}
}
Challenge Solution
import { Component } from 'react';
export default Name extends Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
{/* Change code below this line */}
<h1>{this.props.display}</h1>
{/* Change code above this line */}
</div>
)
}
}
Challenge Tests
[WIP]
Challenge Description
JSX is a syntax, that gets compiled to JS. But it is a syntax nonetheless. Sometimes, for readability, we might need to add comments to our code.
We can put comments inside JSX using the syntax
{/* */}
to wrap around the comment text.<Top /> {/* An inline comment */} <Foot />
Same syntax can be used for multi-line comment
Instructions
Create a single line comment in JSX, inside the
return()
ofrender()
function.
Challenge Seed
import { Component } from 'react';
export default Name extends Component {
constructor(props) {
super(props);
}
render() {
// add comment inside div
return (
<div>
</div>
)
}
}
Challenge Solution
import { Component } from 'react';
export default Name extends Component {
constructor(props) {
super(props);
}
render() {
// add comment inside div
return (
<div>
{/* This is my comment that won't get rendered */}
</div>
)
)
}
}
Challenge Tests
[WIP]
Challenge Description
We learned from the previous example how we can create
props
on JSX components, and the components can render or use dynamic data based on them.To access the dynamic data, we were using
this.props.propertyName
syntax.this.props
is a pure JS object.We cannot directly view it by rendering it on page (because
this.props
contain un-renderable, special properties), but we can view it with dev tools.We will learn more about
componentWillMount()
later in our journey, but for now, you can view the props passed into it by adding aconsole.log
incomponentWillMount()
method of a React component.import React, { Component } from 'react'; export default AppContainer extends Component { constructor(props) { super(props); } componentWillMount () { console.log(this.props); } render() { return ( ) } }
Instructions
The above example prints the object
this.props
in console. Convert the object into JSON-compatible string, and log it
Challenge Seed
import React, { Component } from 'react'; export default AppContainer extends Component { constructor(props) { super(props); } componentWillMount () { // change code below this line console.log(this.props); // change code above this line } render() { return ( ) } }
Challenge Solution
import React, { Component } from 'react'; export default AppContainer extends Component { constructor(props) { super(props); } componentWillMount () { // change code below this line console.log(JSON.stringify(this.props)); // change code above this line } render() { return ( ) } }
Challenge Tests
[WIP]
How are we planning to test these?
We can make use of enzyme.
Do we want to use classnames npm package here?
No need.
@alayek The JSX section should not involve the creation of components.
Challege Description
Arrays let you pass information that can be represented as a collection. A simple To-Do list, or your Facebook newsfeed items - the data to render can be represented using an Array.
React supports passing in arrays and lets you render the elements of the Array inside the component.
render() {
feed = ['cat photo', 'minutephysics', 'john cena', 'buzzfeed post', 'sponsored ad']
return (<NewsFeed data={feed} />)
}
We want there to be a
NewsFeed
component that handles rendering each of the items in the array.Notice the
{}
surroundingfeed
. If you remove that braces, you would get an error, because to put JS expression in JSX, you need to either use quotes (for strings) or curly braces.The challenge comes in the implementation of the
NewsFeed
component. We need to iterate over the array passed asprops
and render each of the item in the array.We will use
Array.prototype.map()
here.
import React, { Component } from 'react';
export default NewsFeed extends Component {
constructor(props) {
super(props);
}
render() {
return (
{this.props.data.map((item, index) => {
<li>{item}</li>
})}
)
}
}
The usage of
map
should be obvious - we are iterating over an array, and foreach
item, we are creating a list of components.Notice that since this is a JS expression, we had to wrap it with
{}
Same goes for
{item}
inside<li></li>
.
Instructions
Instead of putting the whole JS expression inside
{}
withinreturn()
statement, create a JS expression insiderender()
function, and use that to render the list.
import React, { Component } from 'react';
export default NewsFeed extends Component {
constructor(props) {
super(props);
}
render() {
// create your JSX here
const itemsToRender = undefined; // change this line
return (
{/* change code below this line */}
{this.props.data.map((item, index) => {
<li>{item}</li>
})}
{/* change code above this line */}
)
}
}
Challenge Solution
render() {
// create your JSX here
const itemsToRender = this.props.map((item, index) => {
<li>{item}</li>
})
return (
{/* change code below this line */}
{itemsToRender}
{/* change code above this line */}
)
}
Challenge Tests
[WIP]
@alayek I haven't heard anything about these challenges recently. We can now use JSX on beta (staging) so you should be able to finish these. @BerkeleyTrue is working on the multi-tab editor, but we should assume it won't be ready in time for launch, and that these will need to be in script within the same single code editor as style and HTML elements.
@alayek these React challenges are our top curriculum priority. Is there anything I can do to speed up their development? I get asked about these several times a day 😓
Challenge Description
We can set the initial state of using the components
constructor
. It's important that you always usesuper()
when using a constructor.Note: We can set state to be any data type and state can also be modified later on if needed :+1:
Here is an example of setting the initial state of
age
:import React, { Component } from 'react'; export default Name extends Component { constructor() { super(); this.state = { age: 26, }; } }
We can now access age with
this.state.age
.
Instructions
Set the initial state of
this.state.name
to be 'FreeCodeCamp'.Then, render an
h1
tag with the contents beingthis.state.name
.
Challenge Seed
import React, { Component } from 'react'; export default Name extends Component { constructor() { super(); } }
Challenge Solution
import React, { Component } from 'react'; export default Name extends Component { constructor() { super(); this.state = { name: 'FreeCodeCamp', }; } render() { return ( <h1>{this.state.name}</h1> ); } }
setState
Challenge Description
Now that we know how to set the initial state, let's modify the state using
setState
.In this challenge we are going to be creating a counter which increments by 1 every time the button is clicked.
Here is an example of changing the state of
age
to 9 from 26:import React, { Component } from 'react'; export default Name extends Component { constructor() { super(); this.state = { age: 26, }; } change() { this.setState({ age: 9 }); } }
Instructions
- In
click()
change the state ofnum
to benum + 1
which will therefore increment the count by 1.- Render the value of
this.state.num
.
- Using the HTML
onClick
attribute, callclick()
using{this.click}
.
Challenge Seed
import React, { Component } from 'react'; export default Name extends Component { constructor() { super(); this.state = { num: 0, }; } click() { } }
Challenge Solution
import React, { Component } from 'react'; export default Name extends Component { constructor() { super(); this.state = { num: 0, }; } click() { this.setState({ num: num + 1 }); } render() { return ( <button onClick={this.click}>{this.state.num}</button> ); } }
@atjonathan These look great. Any idea what the tests will look like for these?
@QuincyLarson, I'm not sure how that would work. Maybe just regex?
@QuincyLarson Berkeley mentioned we would use Enzyme by AirBnb for React testing. I am yet to take a look at this. Maybe we can find someone to delegate the test creation part?
lelandrichardson/enzyme-example-mocha Test React components with Enzyme and Mocha. This doesn't require a dev-server. Run using npm run test
. I wrote a test for the Add a CSS class with className challenge. I can upload to a repo or gist the test/src files.
I'm not familiar with browser side mocha testing. Is that how you intend to do the challenge testing? @QuincyLarson @alayek @BerkeleyTrue
@t3h2mas yes - that is correct. We want to be able to run the tests 100% client-side to verify whether a camper's inputted code passes our supplied tests. Is this possible to do with Enzyme Mocha? Can you get your "Add a CSS class with className" challenge test to run client-side?
@QuincyLarson yes, I should be able to. I'll update as soon as I can.
@t3h2mas awesome! Yes - see what you can do. Thanks for keeping us posted on this, as this is probably the single biggest ambiguity remaining in terms of finishing up these new challenges :)
@QuincyLarson @BerkeleyTrue @alayek I'm struggling to get Enzyme to work client side. Related issue here. Making a bundle client side would be useful, I tried the browserify build steps but it failed.
Any thoughts? I'm headed back to work but will continue on later tonight/tomorrow.
EDIT: Also, should I be targeting es5 or is es6 okay?
@t3h2mas ES6 will work on FCC, and we'll be using it for everything after a basic introduction.
Regarding Enzyme, I wish I could be of more help. If @BerkeleyTrue can, he may be able to help. He's traveling for a conference this week.
I recommend you keep trying. They have a Gitter room where you could ask for help: https://gitter.im/airbnb/enzyme
@QuincyLarson Do you know if FCC uses either browserify or webpack for es6 compatibility? Otherwise I think some features still may not work on most browsers.
Enzyme has guides for both browserify and webpack integration, just not making an enzyme.js
module.
UPDATE: I am attempting to create a <script>
tag importable bundle by using
window.enzyme = require('enzyme');
w/ webpack. Repo here.
The dependency versions are older because I thought the versions from here might fix the issues I've encountered. Will continue to experiment with getting the file working.
Alternatively we can write the tests and bundle them w/ enzyme into a file and include it. I'm not sure how
window.location
conditions.example:
import { shallow } from 'enzyme';
/* other imports here... */
assert(shallow(component).find('.pill').to.equal(1));
Then bundling this file
@t3h2mas we use Webpack. You can see how we've implemented it here in our gulpfile: https://github.com/FreeCodeCamp/FreeCodeCamp/blob/staging/gulpfile.js
Enzyme does not appear to be available as a UMD, then use React test utils. It can be required just as we require bootstrap and jQuery.
@alayek I suggest calling the component for
Create a simple JSX element
ListItem instead of List because later it is used inside of an unordered list.
Regarding
Render a pair of divs from a component
What form would this take? A pair of divs necessarily must be nested in a single root component, so is the intention to return this:
<div>
<div />
<div />
</div>
Or is the intent something else?
Thanks.
React 0.14 introduced a new way to create components called functional components. Where previously we were defining components that may (or may not) have state, a functional component is stateless. This is useful in cases where we simply pass props to the component (e.g. a presentational component).
Let's look at how to define a stateless functional component:
import React from 'react'; const UserInfo = ({ name, email }) => ( <div> <h1>{name}</h1> <span>{email}</span> </div> );
This is equivalent to the class definition:
import { Component } from 'react'; class UserInfo extends Component { constructor(props) { super(props); } render() { return ( <div> <h1>{this.props.name}</h1> <span>{this.props.email}</span> </div> ); } }
Notice the compact syntax of the functional component. If state is not needed, it is often much shorter to use a function component. Also note that that when passing props to a functional component, we can destructure them (
{ name, email }
). Props can be passed as a single parameter if desired:import React from 'react'; const UserInfo = (props) => ( <div> <h1>{props.name}</h1> <span>{props.email}</span> </div> );
Translate the following
class
syntax React component to a functional component. Use either a single parameter or destructure the props passed to the component.
import { Component } from 'react';
class NewsFeed extends Component {
constructor(props) {
super(props);
}
render() {
return (
<ul>
{
this.props.newsItems.map(item =>
<li>item</li>
)
}
</ul>
);
}
}
import React from 'react';
const NewsFeed = ({ newsItems }) => (
<ul>
{
newsItems.map(item =>
<li>item</li>
)
}
</ul>
);
TBD
@BerkeleyTrue React.test.utils with mocha? In their docs they're using Jest.
Looking to contribute to this effort - Was looking to start with "Create a component using the class syntax" and was wondering if this had value beyond the "Create a Simple JSX element" challenge.
@sjames1958gm you can go ahead with that one if you would like. I would recommend first coming up with what you can, then we can review and update this.
To respond to your query, creating a simple JSX element is just being able to write this syntax:
<div className="my-class">
<ChildComponent />
</div>
While creating a full-fledged component involves:
React.component
render()
methoddefault
Sounds good
Challenge Description A component in React is implemented by extending the React class Component. This minimum requirement for this class is that it must contain a render method. The render method returns the JSX that React uses to build the component HTML. The constructor method for the class will receive any properties that are provided by the parent component. The constructor must pass these to the Component class constructor by calling super(props).
The following shows a component Car that receives a single property model
and is rendered as an <h1>
element containing a string. Note the use of {} to inject javascript code into the JSX.
import { Component } from 'react';
export default class Car extends Component {
constructor(props) {
super(props);
}
render() {
return (
<h1>My car is a {this.props.model}</h1>
);
}
}
Instructions
Create a component class for a component called Greeting. This component will receive a single property name
and should render a <h1>
element with the string "Hello " followed by the the value in the name property.
Challenge Seed
import { Component } from 'react';
export default class Greeting extends Component { // change code below this line
// change code above this line }
Challenge Solution
import { Component } from 'react';
export default class Greeting extends Component {
// change code below this line
constructor(props) {
super(props);
}
render() {
return (
<h1>Hello {this.props.name}</h1>
);
}
// change code above this line
}
Can I get commentary on my submission above before I move on to more. I just saw the thumbs up emoji
@sjames1958gm yes - this looks good. (2 thumbs up means 2 people have reviewed and thought it was good)
This assumes that the reader already knows what a component is (though I don't think anyone has built the " Create a functional component" challenge yet - which would be the ideal place to introduce this concept.
Your style and code examples look good to me.
I took this as intending to teach that a single top level component is required for React component class. Is that correct? If so can we re-title the challenge? I implemented it as if that was true.
Challenge Description A React component uses JSX describe the view for the component. This JSX is returned from the render function of the component. One key restriction on this JSX returned is that there can only be one top level element in the JSX returned. This means that if the element is rendering multiple elements they must be placed into a single "container". This restriction can usually be satisfied by enclosing the desired elements in a div.
Instructions Correct this invalid React component by creating a single top level div containing the existing elements.
Challenge Seed
import { Component } from 'react';
export default class Greeting extends Component {
constructor(props) {
super(props);
}
render() {
return (
{/* change code below this line */}
<h1>Greetings {this.props.name}</h1>
<p>Welcome to React</p>
{/* change code above this line */}
);
}
}
Challenge Solution
import { Component } from 'react';
export default class Greeting extends Component {
constructor(props) {
super(props);
}
render() {
return (
{/* change code below this line */}
<div>
<h1>Greetings {this.props.name}</h1>
<p>Welcome to React</p>
</div>
{/* change code above this line */}
);
}
}
BTW, I found the create a function component in the comments here.
Pass an array to a component using JSX - for this challenge is the expectation that the rendered component would use array.map to render into a li or similar element?
@sjames1958gm you're right! I somehow missed this. I've checked off these component challenges on the checklist up top. Keep up the great work on these.
@sjames1958gm great work!
One thing I wanted to mention - when using comments within JSX components to indicate // change code below this line
, please use JSX syntax for commenting, not native JS syntax.
I fixed the comments
Challenge Description
We saw in the previous challenge how to pass a string to a component through props to add dynamism to our component. But sometimes we have a list of items that we want to pass to our component to render. In this case we can pass an array to the component and use the Array map function to generate the elements. In order to do this we need to embed the call to the map function inside of {} so it will be processed as JavaScript. When creating dynamic elements it is considered a best practice to supply a unique key to each element. (React will issue a warning if you don't.) This key can be any unique value and in the case of an array can be the array index for the item being rendered.
The following Recipe components receives an array of ingredients in props and renders these as <li>
elements of an <ul>
.
import { Component } from 'react';
export default class Recipe extends Component {
constructor(props) {
super(props);
}
render() {
// If ingredients props not supplied use an empty array
const ingredients = this.props.ingredients|| [];
return (
<div>
<p>This recipe has the following ingredients</p>
<ul>
{ ingredients.map((ingredient, index) =>{
/* Note the use of the key property and the item index */
return <li key={index}>{ingredient}</li>
})}
</ul>
</div>
);
}
}
const ingredients = ["1 cup milk", "2 eggs", "1/2 cup sugar", "1 tsp. vanilla"];
ReactDOM.render(
<Recipe ingredients={ingredients}/>,
document.getElementById('container')
);
This will render as:
This recipe has the following ingredients
Instructions
Render the array in this.props.students as <li>
elements in the Class component. Don't forget to include the key property, using the array index as the key value.
Challenge Seed
import { Component } from 'react';
export default class Bootcamp extends Component {
constructor(props) {
super(props);
}
render() {
// If students props not supplied use an empty array
const students = this.props.students || [];
return (
<div>
<p>The following students are enrolled in this bootcamp</p>
<ul>
{/* Add code below this line */}
{/* Add code above this line */}
</ul>
</div>
);
}
}
const students= ["Larry Fine", "Charlie Brown", "Bart Simpson", "Jimmy Neutron"];
ReactDOM.render(
<Bootcamp students={students}/>,
document.getElementById('container')
);
Challenge Solution
import { Component } from 'react';
export default class Bootcamp extends Component {
constructor(props) {
super(props);
}
render() {
// If students props not supplied use an empty array
const students = this.props.students || [];
return (
<div>
<p>The following students are enrolled in this bootcamp</p>
<ul>
{/* Add code below this line */}
{ students.map((student, index) =>{
return <li key={index}>{student}</li>
})}
{/* Add code above this line */}
</ul>
</div>
);
}
}
var students= ["Larry Fine", "Charlie Brown", "Bart Simpson", "Jimmy Neutron"];
ReactDOM.render(
<Bootcamp students={students}/>,
document.getElementById('container')
);
@sjames1958gm great work! One thing you might want to mention, is that you can use something like this to avoid errors like undefined has no method named 'map'
const students = this.props.students || []
Basically, inside the component that would render the array, you should typically check whether the array you are accessing is actually not undefined
.
A lesson I learned from my C segfault days - don't access pointer fields without wrapping it in if (pointer != NULL)
. Solves 99% of segmentation faults!
Updated with great suggestion from alayek to protect against null props
@BerkeleyTrue is in charge of coordinating the creation of these challenges, but he needs your help.
Here are the challenges we have currently planned:
this.props
this.state
setState
edit(@berkeley): proptypes/defaultProps added. Some state challenges added
For each challenge, please reply to this GitHub issue with: