{"id":19288475,"url":"https://github.com/sscaff1/react-workshop","last_synced_at":"2026-05-04T17:36:34.520Z","repository":{"id":96768616,"uuid":"96716103","full_name":"sscaff1/react-workshop","owner":"sscaff1","description":"Dev Meeting solutions and supplemental notes","archived":false,"fork":false,"pushed_at":"2017-07-12T17:03:56.000Z","size":37,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-11-14T17:09:18.642Z","etag":null,"topics":["introduction","react","react-components","tutorial"],"latest_commit_sha":null,"homepage":"https://react-workshop-vgodbbaefe.now.sh/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sscaff1.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-07-09T22:54:10.000Z","updated_at":"2017-07-15T06:55:00.000Z","dependencies_parsed_at":"2023-07-11T15:16:36.598Z","dependency_job_id":null,"html_url":"https://github.com/sscaff1/react-workshop","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/sscaff1/react-workshop","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sscaff1%2Freact-workshop","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sscaff1%2Freact-workshop/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sscaff1%2Freact-workshop/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sscaff1%2Freact-workshop/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sscaff1","download_url":"https://codeload.github.com/sscaff1/react-workshop/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sscaff1%2Freact-workshop/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32618218,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-04T10:08:07.713Z","status":"ssl_error","status_checked_at":"2026-05-04T10:08:02.005Z","response_time":58,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["introduction","react","react-components","tutorial"],"created_at":"2024-11-09T22:09:08.315Z","updated_at":"2026-05-04T17:36:34.514Z","avatar_url":"https://github.com/sscaff1.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Functional JavaScript\nThe below functions are commonly used to form React components. This is a small intro into them.\nNote that all of the below methods are part of the array prototype. Any type of value (strings, numbers, objects, arrays) can make up the contents of the array on which these methods are executed.\n## map\nThis method returns a *new array* by calling the provided callback function against all of the elements of the array. The callback has 3 arguments:\n- the current value\n- the index of the current value\n- the original array\nThe map method does not mutate the original array.\nIn React, we often use the first two arguments in this callback to map an array in a component.\n```js\nconst todos = ['todo 1', 'todo 2', 'todo 3'];\nconst App = () =\u003e {\n  return (\n    \u003cul\u003e\n      {todos.map((todo, i) =\u003e ( // notice we use the first and second argument\n        \u003cli key={`todo-${i}`}\u003e{todo}\u003c/li\u003e // we implicitly return the list item\n      ))}\n    \u003c/ul\u003e\n  );\n}\n```\n\nThe above component will produce an unordered list with our `todos` array as the list items.\n\n## filter\nSimilar to the map method, the `filter`, method returns a *new array*. As the name implies, it's used to filter out values. The function provide has the same 3 arguments as the above map method. The filter method does not mutate the original array. The filter method returns an array with the elements that return `true` from the callback.\nIn React, we often use this method. Here is an example.\n```js\nconst todos = [\n  { name: 'todo 1', status: 'done' },\n  { name: 'todo 2', status: 'in progress' },\n  { name: 'todo 3', status: 'not started' },\n  { name: 'todo 4', status: 'in progress' },\n  { name: 'todo 5', status: 'done' },\n];\nconst DoneTodos = () =\u003e {\n  return (\n    \u003cdiv\u003e\n      \u003ch1\u003eBelow are our done todos\u003c/h1\u003e\n      \u003cul\u003e\n        {todos.filter((todo) =\u003e (todo.status === 'done')).map((todo, i) =\u003e (\n          \u003cli key={`done-${i}`}\u003e\n            {todo.name}\n          \u003c/li\u003e\n        ))}\n    \u003c/div\u003e\n  );\n}\n```\n# ES6\n## Arrow Functions\nIn ES6, we have the option of writing functions using a shorter syntax called arrow functions. The following are equivelent:\n```js\nfunction func1(param1) {\n  return param1;\n}\nconst func12 = (param1) =\u003e {\n  return param1;\n}\nconst func3 = (param1) =\u003e param1 // note here we can implicitly return null\nconst func4 = param1 =\u003e param1 // since there is only 1 parameter in the function the parethensis can be dropped\n```\nUnlike regular functions, arrow functions do not bind `this`. With regular functions, a new `this` object was created with every new function. This proved to be annoying in object oriented programming.\n```js\nconst START_TIME = 300;\nconst brokenCar = {\n  startSound: 'voom',\n  start() {\n    window.setTimeout(function() {\n      // this is undefined in strict mode or the global object (window in the case of the browswer) in non-strict mode\n      console.log(this.startSound) \n    }, START_TIME);\n  }\n};\n\nconst workingCar = {\n  startSound: 'voom',\n  start() {\n    window.setTimeout(() =\u003e {\n      // this now refers to the working car since the arrow function does not bind this\n      console.log(this.startSound) \n    }, START_TIME);\n  }\n};\n```\n## Classes\n`class` was introduced in ES6. It's important to note, however; that this is not a true class (like in Java or C#). Instead classes are simply syntax sugar to create special functions that provide a simplier approach to objects and inheritance. \nLook at the following example:\n```js\nclass Car {\n  constructor(props) {\n    this.model = props.model;\n    this.color = props.color;\n  }\n  details() {\n    console.log(`A ${this.color} ${this.model}`);\n  }\n}\nclass Toyota extends Car {\n  constructor(props) {\n    super(props);\n    this.model = 'Toyota';\n  }\n}\n\nconst car1 = new Toyota({ color: 'red' });\ncar1.details(); // logs: A red Toyota\n```\nNice that we have a Car class and Toyota extends this class. By calling `super()` in the constructor, it calls the constructor of the base class `Car`. The constructor of `Toyota` is called with every new instance of the class. Using babel, we can see that these are infact just functions. In fact the constructor of each class isn't special at all, it's just a regular function.\n\n```js\n'use strict';\n\nvar _createClass = function () { function defineProperties(target, props) { for (var i = 0; i \u003c props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\nfunction _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return call \u0026\u0026 (typeof call === \"object\" || typeof call === \"function\") ? call : self; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" \u0026\u0026 superClass !== null) { throw new TypeError(\"Super expression must either be null or a function, not \" + typeof superClass); } subClass.prototype = Object.create(superClass \u0026\u0026 superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nvar Car = function () {\n  function Car(props) {\n    _classCallCheck(this, Car);\n\n    this.model = props.model;\n    this.color = props.color;\n  }\n\n  _createClass(Car, [{\n    key: 'details',\n    value: function details() {\n      console.log('A ' + this.color + ' ' + this.model);\n    }\n  }]);\n\n  return Car;\n}();\n\nvar Toyota = function (_Car) {\n  _inherits(Toyota, _Car);\n\n  function Toyota(props) {\n    _classCallCheck(this, Toyota);\n\n    var _this = _possibleConstructorReturn(this, (Toyota.__proto__ || Object.getPrototypeOf(Toyota)).call(this, props));\n\n    _this.model = 'Toyota';\n    return _this;\n  }\n\n  return Toyota;\n}(Car);\n\nvar car1 = new Toyota({ color: 'red' });\ncar1.details();\n```\n\nYou can also see why classes were introduced. Classes can be difficult to implement in ES5 and readability is even worse. in ES6, classes are easy to implement and read. Classes have become the defacto way to write components in React that require life-cycle methods. We'll go over these shortly.\n\n# React\nThe following is supplementary notes to the slideshow presented in class.\nReact is a component based view library (not a *framework*) used to build dynamic, fast user interfaces.\nA great way to get started with React is using Create React App. The only requirement is Node v4 or above.\n\n## Slide 8 notes:\n- A capital letter A for app signifies that we are using a dev created component which must be in scope in order to successfully render.\n- index.js is actually referenced in our index.html in our public folder. Notice in our public/index.html that there is a div with an id of root. App is in scope in this file because we import it from App.js.\n- Other notes: JSX is *NOT* HTML. It's JavaScript. We can actually write React components without JSX although this becomes unreadable very quickly. Look at the following two examples from the React docs which are equivilant. When compiled with webpack or any other build tool, the build tool will transpile the with JSX example to the without JSX example below. Notice that everything is just JavaScript which means React is nothing but JavaScript.\n```js\n// with JSX\nclass HelloMessage extends React.Component {\n  render() {\n    return \u003cdiv\u003eHello {this.props.name}\u003c/div\u003e;\n  }\n}\n\nReactDOM.render(\u003cHelloMessage name=\"John\" /\u003e, mountNode);\n// without JSX\nclass HelloMessage extends React.Component {\n  render() {\n    return React.createElement(\n      \"div\",\n      null,\n      \"Hello \",\n      this.props.name\n    );\n  }\n}\n\nReactDOM.render(React.createElement(HelloMessage, { name: \"John\" }), mountNode);\n```\n## Slide 9 Notes:\n- React must be in scope in order to use JSX\n- React components can be written in several ways. Let's look at the following:\n```js\nimport React from 'react';\n// ES5\nconst App = React.createClass({\n  getInitialState() {\n    return {\n      count: 0\n    };\n  }, // notice the comma\n  increment() {\n    this.setState({ count: this.state.count + 1 });\n  },\n  render() {\n    return (\n      \u003cbutton onClick={this.increment}\u003e\n        {this.state.count}\n      \u003c/button\u003e\n    );\n  }\n});\n// ES6\nclass App extends React.Component {\n  constructor(props, context) { // notice the constructor\n    super(props, context);\n    this.state = {\n      count: 0\n    };\n    this.increment = this.increment.bind(this); // notice we need to bind this\n  }; // notice no comma; semicolon instead\n\n  increment() {\n    this.setState({ count: this.state.count + 1 })\n  };\n\n  render() {\n    return (\n      \u003cbutton onClick={this.increment}\u003e\n        {this.state.count}\n      \u003c/button\u003e\n    );\n  };\n}\n// React with Babel\nclass App extends React.Component {\n  state = { // state is directly on the class\n    count: 0\n  };\n\n  increment = () =\u003e { // property initializer; implicitly binds this\n    this.setState({ count: this.state.count + 1 })\n  }\n\n  render() {\n    return (\n      \u003cbutton onClick={this.increment}\u003e\n        {this.state.count}\n      \u003c/button\u003e\n    );\n  }\n}\n\n// Pure functional component - With arrow function\nconst App = () =\u003e (\n  \u003ch1\u003eI am pure\u003c/h1\u003e\n);\n// Pure functional component - without arrow function\nfunction App() {\n  return (\n    \u003ch1\u003eI am also pure\u003c/h1\u003e\n  );\n}\n```\n## Slide 10 Notes:\n- Remember JSX is not HTML\n- React can currently only return one child. This is changing with React Fiber (you'll be able to render an array of children).\n- Hard coded data does not have to sit inside the class (this is simply a matter of preference). All it has to do is be in scope.\n- {} anything inside these brackets just indicates to React that I want to escape JSX so that I can use regular JavaScript.\n## Slide 13 Notes\n- Remember that a key property is required when you map over an array. \n- What makes a good key?\n  * A key tells react which elements in a list have been updated, removed or added. So the best keys are going to be unique keys. Use array indexes only as a last resort and try to make them unique even if you are doing so. Here are some examples:\n```\n// bad\nlist.map((item, i) =\u003e \u003cItem key={i} /\u003e\n\n// better\nlist.map((item, i) =\u003e \u003cItem key={`mylist-${i}`} /\u003e\n\n// best\nlist.map(item =\u003e \u003cItem key={item.id} /\u003e\n```\n## Slide 14 Notes\n- Thinking in React requires you to think of component not pages of your application. A component is a small piece of your application. One of the benefits of React is that these pieces are reusable throughout your application. The more experienced you become with React the more you'll consider reusability in your components.\n## Slide 15 Notes\n- Components accept two arguments - props and context.\n  * `props` is the properties of the components passed by it's parent. This is the first argument of a component.\n  * `context` is implicitly passed be either it's parent or on a higher level. The vast majority of application do not need context. It's API is still considered experimental and likely to change. It can often lead to confusion in an applications since it's not immediately clear how context is passed.\n- You can pass props like follows:\n  ```js\n  const onClickHandler = () =\u003e {\n    console.log('Button Pressed');\n  }\n  // without ES6 destructuring \n  const Button = (props) =\u003e {\n    console.log(props); // an object with the keys color, onPress, label\n    return (\n      \u003cbutton onClick={props.onPress} style={{ color: props.color }}\u003e\n        {props.label}\n      \u003c/button\u003e\n    );\n  }\n  // without ES6 spread operator\n  const App = () =\u003e (\n    \u003cButton color=\"blue\" onPress={onClickHandler} label=\"My Button\" /\u003e\n  );\n  // with ES6 destructuring\n  const Button = ({ color, onPress, label }) =\u003e {\n    // notice since the key and value are the same we can use es6 object literal\n    // { color } === { color: color }\n    return (\n      \u003cbutton onClick={onPress} style={{ color }}\u003e\n        {label}\n      \u003c/button\u003e\n    );\n  }\n  // with ES6 spread operator\n  const buttonProps = {\n    color: 'blue',\n    onPress: onClickHandler,\n    label: 'My Button'\n  };\n  const App = () =\u003e (\n    \u003cButton {...props} /\u003e\n  );\n  ```\n- ES6 Destructuring allows you to assign variables based on the keys of an object or array\n```js\nconst person = { name: 'Joe', age: 27, weight: 170 };\n// using destructuring we can create variables name, age, weight based on the keys of the person object\nconst { name, age, weight } = person\n// notice that we can also destructure in the parameters of a function (like we do with React)\nfunction logDetails({ name, age, weight }) {\n  console.log(name, age, weight);\n}\nlogDetails(person);\n```\n## Slide 18\n- Notice we can also use destructuring on the import statement\n## Slide 19 \u0026 20 \u0026 21\n- `this.setState()` is used to change state in a React Component. The setState function can accept either a function or object as the first parameter and a callback function as it's second parameter. When using a function as the first parameter, the function has 2 parameter state and props. You're expected to return an object representing the new state. Setting state will trigger the component to re-render unless specific logic is placed in `shouldComponentUpdate` to prevent an update. The callback function runs after the re-render happens (which means it reflects the new state of the component). In general, logic in the callback should be placed in `componentDidUpdate`. setState will merge the current state with the new state passed into the function.\n```js\n// setting state with an object\nthis.setState({ count: this.state.count + 1 });\n// setting state with an function\nthis.setState((prevState, props) =\u003e {\n  return { count: prevState.count + 1 };\n});\n```\n- React will try to avoid re-renders so setting state so it's important to note that the only way to guarantee that that state is set based on the previous state is to use a function as the first parameter. Observe the following example:\n```js\nhandleClick = () =\u003e {\n  // initial count = 0\n  this.setState({ count: this.state.count + 1 })\n  this.setState({ count: this.state.count + 1 })\n  // new state is count: 1 despite calling setState twice\n}\nhandleClick = () =\u003e {\n  // initial count = 0\n  this.setState((prevState) =\u003e ({ count: prevState.count + 1 }))\n  this.setState((prevState) =\u003e ({ count: prevState.count + 1 }))\n  // new state is count: 2 as expected\n}\n```\n## Slide 24\n- react-router also provides a `Switch` component. The `Switch` component will render exactly one route based on the URL path. Without `Switch`, the `Route` component will render all routes that match the current path. This is by design in order to render content like side bars. In general, if you are going to another page, use the `Switch` component.\n## Slide 25\n- react-router now provides `NavLink` which is a special version of `Link` that can add styling to your Link based on the current path of your application.\n# Redux\nHonestly the redux docs are so good that restating information from the docs would be pointless. Check out the redux docs at http://redux.js.org/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsscaff1%2Freact-workshop","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsscaff1%2Freact-workshop","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsscaff1%2Freact-workshop/lists"}