{"id":15889043,"url":"https://github.com/baxtergu/react-hn","last_synced_at":"2025-04-02T16:47:53.080Z","repository":{"id":104712342,"uuid":"58353085","full_name":"baxtergu/react-hn","owner":"baxtergu","description":null,"archived":false,"fork":false,"pushed_at":"2016-05-09T06:30:50.000Z","size":806,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-08T07:27:47.425Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/baxtergu.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":"2016-05-09T06:19:03.000Z","updated_at":"2016-05-09T06:21:16.000Z","dependencies_parsed_at":"2023-07-23T01:15:52.540Z","dependency_job_id":null,"html_url":"https://github.com/baxtergu/react-hn","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/baxtergu%2Freact-hn","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/baxtergu%2Freact-hn/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/baxtergu%2Freact-hn/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/baxtergu%2Freact-hn/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/baxtergu","download_url":"https://codeload.github.com/baxtergu/react-hn/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246854826,"owners_count":20844828,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":[],"created_at":"2024-10-06T06:40:59.214Z","updated_at":"2025-04-02T16:47:53.058Z","avatar_url":"https://github.com/baxtergu.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"React HN (Clone \u0026 Modified from: https://github.com/mking/react-hn)\n===\nThis is a visual React tutorial. This tutorial should give you a feel for \"growing\" a React UI from small, modular parts. By the end of this tutorial, you will have built the [HN front page in React](https://mking.github.io/react-hn).\n\n\u003e Note: This tutorial covers React, Browserify, and CSS. It does not cover event handling (not needed for the HN front page), state (not needed for the HN front page), or Flux.\n\nThis tutorial has five parts:\n\n 1. [Setup](#setup)\n\n 1. [NewsItem component](#newsitem)\n\n    \u003cimg src=\"img/NewsItem@2x.png\" width=\"532\"\u003e\n\n 1. [NewsHeader component](#newsheader)\n\n    \u003cimg src=\"img/NewsHeader@2x.png\" width=\"532\"\u003e\n\n 1. [NewsList component](#newslist)\n\n    \u003cimg src=\"img/NewsList@2x.png\" width=\"532\"\u003e\n\n 1. [Display live data from the Hacker News API](#hacker-news-api)\n\n---\n\nSetup\n---\n 1. Create the project directory structure.\n    ```bash\n    mkdir -p hn/{build/js,css,html,img,js,json}\n    cd hn\n    ```\n\n    \u003e Note: We will be building the project from scratch. The solution in this repo is meant primarily to be a reference.\n\n 1. [Download the sample data](https://raw.githubusercontent.com/mking/react-hn/master/json/items.json) into /json.\n\n 1. Download [y18.gif](https://news.ycombinator.com/y18.gif) and [grayarrow2x.gif](https://news.ycombinator.com/grayarrow2x.gif) into /img.\n\n 1. Create /package.json.\n    ```json\n    {\n      \"name\": \"hn\",\n      \"version\": \"0.1.0\",\n      \"private\": true,\n      \"browserify\": {\n        \"transform\": [\n          [\"reactify\"]\n        ]\n      }\n    }\n    ```\n\n 1. Install Browserify, React, and tools.\n    ```bash\n    # These dependencies are required for running the app.\n    npm install --save react jquery lodash moment\n\n    # These dependencies are required for building the app.\n    npm install --save-dev browserify watchify reactify\n\n    # These dependencies are globally installed command line tools.\n    npm install -g browserify watchify http-server\n    ```\n\n[Next](#newsitem)\n\n---\n\nNewsItem\n---\n 1. [Display the title.](#newsitem-title)\n\n    \u003cimg src=\"img/NewsItemTitle.png\" width=\"110\"\u003e\n\n 1. [Add the domain.](#newsitem-domain)\n\n    \u003cimg src=\"img/NewsItemDomain.png\" width=\"213\"\u003e\n\n 1. [Add the subtext.](#newsitem-subtext)\n\n    \u003cimg src=\"img/NewsItemSubtext.png\" width=\"268\"\u003e\n\n 1. [Add the rank and vote.](#newsitem-rank-and-vote)\n\n    \u003cimg src=\"img/NewsItemRankVote.png\" width=\"297\"\u003e\n\n[Previous](#setup) \u0026middot; [Next](#newsitem-title)\n\n---\n\nNewsItem Title\n---\n 1. Create a new JS file: /js/NewsItem.js.\n    ```javascript\n    var $ = require('jquery');\n    var React = require('react');\n\n    var NewsItem = React.createClass({\n      render: function () {\n        return (\n          \u003cdiv className=\"newsItem\"\u003e\n            \u003ca className=\"newsItem-titleLink\" href={this.props.item.url}\u003e{this.props.item.title}\u003c/a\u003e\n          \u003c/div\u003e\n        );\n      }\n    });\n\n    module.exports = NewsItem;\n    ```\n\n    \u003e Note: You should be able to paste this code directly into your JS file.\n\n 1. Create a new JS file: /js/NewsItemTest.js.\n    ```javascript\n    var $ = require('jquery');\n    var NewsItem = require('./NewsItem');\n    var React = require('react');\n\n    $.ajax({\n      url: '/json/items.json'\n    }).then(function (items) {\n      // Log the data so we can inspect it in the developer console.\n      console.log('items', items);\n      // Use a fake rank for now.\n      React.render(\u003cNewsItem item={items[0]} rank={1}/\u003e, $('#content')[0]);\n    });\n    ```\n\n    \u003e Note: This lets us develop the NewsItem component in isolation, rather than requiring it to be hooked into the full app.\n\n 1. Create a new CSS file: /css/NewsItem.css. We are following [Jacob Thornton's CSS style guide](https://medium.com/@fat/mediums-css-is-actually-pretty-fucking-good-b8e2a6c78b06).\n    ```css\n    .newsItem {\n      color: #828282;\n      margin-top: 5px;\n    }\n\n    .newsItem-titleLink {\n      color: black;\n      font-size: 10pt;\n      text-decoration: none;\n    }\n    ```\n\n 1. Create a new CSS file: /css/app.css.\n    ```css\n    body {\n      font-family: Verdana, sans-serif;\n    }\n    ```\n\n 1. Create a new HTML file: /html/NewsItem.html.\n    ```html\n    \u003c!DOCTYPE html\u003e\n    \u003chtml\u003e\n      \u003chead\u003e\n        \u003cmeta charset=\"utf-8\"\u003e\n        \u003ctitle\u003eNewsItem\u003c/title\u003e\n        \u003clink href=\"../css/NewsItem.css\" rel=\"stylesheet\"\u003e\n        \u003clink href=\"../css/app.css\" rel=\"stylesheet\"\u003e\n      \u003c/head\u003e\n      \u003cbody\u003e\n        \u003cdiv id=\"content\"\u003e\u003c/div\u003e\n        \u003cscript src=\"../build/js/NewsItemTest.js\"\u003e\u003c/script\u003e\n      \u003c/body\u003e\n    \u003c/html\u003e\n    ```\n\n 1. Start Watchify. This compiles your React (JSX) components into ordinary JavaScript.\n    ```bash\n    watchify -v -o build/js/NewsItemTest.js js/NewsItemTest.js\n    ```\n\n 1. Start the HTTP server.\n    ```bash\n    http-server -p 8888\n    ```\n\n 1. Visit [http://localhost:8888/html/NewsItem.html](http://localhost:8888/html/NewsItem.html). You should see the following.\n\n    \u003cimg src=\"img/NewsItemTitle.png\" width=\"110\"\u003e\n\n    \u003cimg src=\"img/DeveloperConsole.png\" width=\"274\"\u003e\n\n[Previous](#newsitem) \u0026middot; [Next](#newsitem-domain)\n\nNewsItem Domain\n---\n 1. Update the JS.\n    ```javascript\n    // ...\n    var url = require('url');\n\n    var NewsItem = React.createClass({\n      // ...\n\n      getDomain: function () {\n        return url.parse(this.props.item.url).hostname;\n      },\n\n      render: function () {\n        return (\n          \u003cdiv className=\"newsItem\"\u003e\n            ...\n            \u003cspan className=\"newsItem-domain\"\u003e\n              ({this.getDomain()})\n            \u003c/span\u003e\n          \u003c/div\u003e\n        );\n      }\n    ```\n\n    \u003e Note: This code should be added onto the existing code in /js/NewsItem.js.\n\n 1. Update the CSS.\n    ```css\n    .newsItem-domain {\n      font-size: 8pt;\n      margin-left: 5px;\n    }\n    ```\n\n    \u003e Note: This code should be added onto the existing code in /css/NewsItem.css.\n\n 1. Refresh the browser. You should see the following.\n\n    \u003cimg src=\"img/NewsItemDomain.png\" width=\"213\"\u003e\n\n[Previous](#newsitem-title) \u0026middot; [Next](#newsitem-subtext)\n\n---\n\nNewsItem Subtext\n---\n 1. Update the JS. Note: We are factoring out the title part into its own method.\n    ```javascript\n    // ...\n    var moment = require('moment');\n\n    var NewsItem = React.createClass({\n      // ...\n\n      getCommentLink: function () {\n        var commentText = 'discuss';\n        if (this.props.item.kids \u0026\u0026 this.props.item.kids.length) {\n          // This only counts top-level comments.\n          // To get the full count, recursively get item details for this news item.\n          commentText = this.props.item.kids.length + ' comments';\n        }\n\n        return (\n          \u003ca href={'https://news.ycombinator.com/item?id=' + this.props.item.id}\u003e{commentText}\u003c/a\u003e\n        );\n      },\n\n      getSubtext: function () {\n        return (\n          \u003cdiv className=\"newsItem-subtext\"\u003e\n            {this.props.item.score} points by \u003ca href={'https://news.ycombinator.com/user?id=' + this.props.item.by}\u003e{this.props.item.by}\u003c/a\u003e {moment.utc(this.props.item.time * 1000).fromNow()} | {this.getCommentLink()}\n          \u003c/div\u003e\n        );\n      },\n\n      getTitle: function () {\n        return (\n          \u003cdiv className=\"newsItem-title\"\u003e\n            ...\n          \u003c/div\u003e\n        );\n      },\n\n      render: function () {\n        return (\n          \u003cdiv className=\"newsItem\"\u003e\n            {this.getTitle()}\n            {this.getSubtext()}\n          \u003c/div\u003e\n        );\n      }\n    ```\n\n 1. Update the CSS.\n    ```css\n    .newsItem-subtext {\n      font-size: 7pt;\n    }\n\n    .newsItem-subtext \u003e a {\n      color: #828282;\n      text-decoration: none;\n    }\n\n    .newsItem-subtext \u003e a:hover {\n      text-decoration: underline;\n    }\n    ```\n\n 1. Refresh the browser. You should see the following.\n\n    \u003cimg src=\"img/NewsItemSubtext.png\" width=\"268\"\u003e\n\n[Previous](#newsitem-domain) \u0026middot; [Next](#newsitem-rank-and-vote)\n\n---\n\nNewsItem Rank and Vote\n---\n 1. Update the JS.\n     ```javascript\n    var NewsItem = React.createClass({\n      // ...\n\n      getRank: function () {\n        return (\n          \u003cdiv className=\"newsItem-rank\"\u003e\n            {this.props.rank}.\n          \u003c/div\u003e\n        );\n      },\n\n      getVote: function () {\n        return (\n          \u003cdiv className=\"newsItem-vote\"\u003e\n            \u003ca href={'https://news.ycombinator.com/vote?for=' + this.props.item.id + '\u0026dir=up\u0026whence=news'}\u003e\n              \u003cimg src=\"../img/grayarrow2x.gif\" width=\"10\"/\u003e\n            \u003c/a\u003e\n          \u003c/div\u003e\n        );\n      },\n\n      render: function () {\n        return (\n          \u003cdiv className=\"newsItem\"\u003e\n            {this.getRank()}\n            {this.getVote()}\n            \u003cdiv className=\"newsItem-itemText\"\u003e\n              {this.getTitle()}\n              {this.getSubtext()}\n            \u003c/div\u003e\n          \u003c/div\u003e\n        );\n      }\n    ```\n\n 1. Update the CSS.\n    ```css\n    .newsItem {\n      /* ... */\n      align-items: baseline;\n      display: flex;  \n    }\n\n    .newsItem-itemText {\n      flex-grow: 1;\n    }\n\n    .newsItem-rank {\n      flex-basis: 25px;\n      font-size: 10pt;\n      text-align: right;\n    }\n\n    .newsItem-vote {\n      flex-basis: 15px;\n      text-align: center;\n    }\n    ```\n\n 1. Refresh the browser. You should see the following.\n\n    \u003cimg src=\"img/NewsItemRankVote.png\" width=\"297\"\u003e\n\n    You have now implemented an HN news item in React.\n\n    \u003cimg src=\"img/NewsItem@2x.png\" width=\"532\"\u003e\n\n[Previous](#newsitem-subtext) \u0026middot; [Next](#newsheader)\n\n---\n\nNewsHeader\n---\n1. [Display the logo and title.](#newsheader-logo-and-title)\n\n   \u003cimg src=\"img/NewsHeaderLogoTitle.png\" width=\"140\"\u003e\n\n1. [Add the nav links.](#newsheader-nav)\n\n   \u003cimg src=\"img/NewsHeaderNav.png\" width=\"453\"\u003e\n\n1. [Add the login link.](#newsheader-login)\n\n   \u003cimg src=\"img/NewsHeaderLogin.png\" width=\"530\"\u003e\n\n[Previous](#newsitem-rank-and-vote) \u0026middot; [Next](#newsheader-logo-and-title)\n\n---\n\nNewsHeader Logo and Title\n---\n 1. Create a new JS file: /js/NewsHeader.js.\n    ```javascript\n    var $ = require('jquery');\n    var React = require('react');\n\n    var NewsHeader = React.createClass({\n      getLogo: function () {\n        return (\n          \u003cdiv className=\"newsHeader-logo\"\u003e\n            \u003ca href=\"https://www.ycombinator.com\"\u003e\u003cimg src=\"../img/y18.gif\"/\u003e\u003c/a\u003e\n          \u003c/div\u003e\n        );\n      },\n\n      getTitle: function () {\n        return (\n          \u003cdiv className=\"newsHeader-title\"\u003e\n            \u003ca className=\"newsHeader-textLink\" href=\"https://news.ycombinator.com\"\u003eHacker News\u003c/a\u003e\n          \u003c/div\u003e\n        );\n      },\n\n      render: function () {\n        return (\n          \u003cdiv className=\"newsHeader\"\u003e\n            {this.getLogo()}\n            {this.getTitle()}\n          \u003c/div\u003e\n        );\n      }\n    });\n\n    module.exports = NewsHeader;\n    ```\n\n 1. Create a new JS file: /js/NewsHeaderTest.js.\n    ```javascript\n    var $ = require('jquery');\n    var NewsHeader = require('./NewsHeader');\n    var React = require('react');\n\n    React.render(\u003cNewsHeader/\u003e, $('#content')[0]);\n    ```\n\n 1. Create a new CSS file: /css/NewsHeader.css.\n    ```css\n    .newsHeader {\n      align-items: center;\n      background: #ff6600;\n      color: black;\n      display: flex;\n      font-size: 10pt;\n      padding: 2px;\n    }\n\n    .newsHeader-logo {\n      border: 1px solid white;\n      flex-basis: 18px;\n      height: 18px;\n    }\n\n    .newsHeader-textLink {\n      color: black;\n      text-decoration: none;\n    }\n\n    .newsHeader-title {\n      font-weight: bold;\n      margin-left: 4px;\n    }\n    ```\n\n 1. Create a new HTML file: /html/NewsHeader.html.\n    ```html\n    \u003c!DOCTYPE html\u003e\n    \u003chtml\u003e\n      \u003chead\u003e\n        \u003cmeta charset=\"utf-8\"\u003e\n        \u003ctitle\u003eNewsHeader\u003c/title\u003e\n        \u003clink href=\"../css/NewsHeader.css\" rel=\"stylesheet\"\u003e\n        \u003clink href=\"../css/app.css\" rel=\"stylesheet\"\u003e\n      \u003c/head\u003e\n      \u003cbody\u003e\n        \u003cdiv id=\"content\"\u003e\u003c/div\u003e\n        \u003cscript src=\"../build/js/NewsHeaderTest.js\"\u003e\u003c/script\u003e\n      \u003c/body\u003e\n    \u003c/html\u003e\n    ```\n\n 1. Start Watchify.\n    ```bash\n    watchify -v -o build/js/NewsHeaderTest.js js/NewsHeaderTest.js\n    ```\n\n 1. Start the HTTP server if necessary.\n    ```bash\n    http-server -p 8888\n    ```\n\n 1. Visit [http://localhost:8888/html/NewsHeader.html](http://localhost:8888/html/NewsHeader.html). You should see the following.\n\n    \u003cimg src=\"img/NewsHeaderLogoTitle.png\" width=\"140\"\u003e\n\n[Previous](#newsheader) \u0026middot; [Next](#newsheader-nav)\n\n---\n\nNewsHeader Nav\n---\n 1. Update the JS.\n    ```javascript\n    // ...\n    var _ = require('lodash');\n\n    var NewsHeader = React.createClass({\n      // ...\n\n      getNav: function () {\n        var navLinks = [\n          {\n            name: 'new',\n            url: 'newest'\n          },\n          {\n            name: 'comments',\n            url: 'newcomments'\n          },\n          {\n            name: 'show',\n            url: 'show'\n          },\n          {\n            name: 'ask',\n            url: 'ask'\n          },\n          {\n            name: 'jobs',\n            url: 'jobs'\n          },\n          {\n            name: 'submit',\n            url: 'submit'\n          }\n        ];\n\n        return (\n          \u003cdiv className=\"newsHeader-nav\"\u003e\n            {_(navLinks).map(function (navLink) {\n              return (\n                \u003ca key={navLink.url} className=\"newsHeader-navLink newsHeader-textLink\" href={'https://news.ycombinator.com/' + navLink.url}\u003e\n                  {navLink.name}\n                \u003c/a\u003e\n              );\n            }).value()}\n          \u003c/div\u003e\n        );\n      },\n\n      render: function () {\n        return (\n          \u003cdiv className=\"newsHeader\"\u003e\n            ...\n            {this.getNav()}\n          \u003c/div\u003e\n        );\n      }\n    ```\n\n 1. Update the CSS.\n    ```css\n    .newsHeader-nav {\n      flex-grow: 1;\n      margin-left: 10px;\n    }\n\n    .newsHeader-navLink:not(:first-child)::before {\n      content: ' | ';\n    }\n    ```\n\n 1. Refresh the browser. You should see the following.\n\n    \u003cimg src=\"img/NewsHeaderNav.png\" width=\"453\"\u003e\n\n[Previous](#newsheader-logo-and-title) \u0026middot; [Next](#newsheader-login)\n\n---\n\nNewsHeader Login\n---\n 1. Update the JS.\n    ```javascript\n    var NewsHeader = React.createClass({\n      // ...\n\n      getLogin: function () {\n        return (\n          \u003cdiv className=\"newsHeader-login\"\u003e\n            \u003ca className=\"newsHeader-textLink\" href=\"https://news.ycombinator.com/login?whence=news\"\u003elogin\u003c/a\u003e\n          \u003c/div\u003e\n        );\n      },\n\n      render: function () {\n        return (\n          \u003cdiv className=\"newsHeader\"\u003e\n            ...\n            {this.getLogin()}\n          \u003c/div\u003e\n        );\n      }\n    ```\n\n 1. Update the CSS.\n    ```css\n    .newsHeader-login {\n      margin-right: 5px;\n    }\n    ```\n\n 1. Refresh the browser. You should see the following.\n\n    \u003cimg src=\"img/NewsHeaderLogin.png\" width=\"530\"\u003e\n\n    You have now implemented the HN header in React.\n\n    \u003cimg src=\"img/NewsHeader@2x.png\" width=\"532\"\u003e\n\n[Previous](#newsheader-nav) \u0026middot; [Next](#newslist)\n\n---\n\nNewsList\n---\n1. [Display the header and items.](#newslist-header-and-items)\n\n   \u003cimg src=\"img/NewsListHeaderItems.png\" width=\"270\"\u003e\n\n1. [Add the more link.](#newslist-more)\n\n   \u003cimg src=\"img/NewsListMore.png\" width=\"136\"\u003e\n\n[Previous](#newsheader-login) \u0026middot; [Next](#newslist-header-and-items)\n\n---\n\nNewsList Header and Items\n---\n 1. Create a new JS file: /js/NewsList.js.\n    ```javascript\n    var _ = require('lodash');\n    var NewsHeader = require('./NewsHeader');\n    var NewsItem = require('./NewsItem');\n    var React = require('react');\n\n    var NewsList = React.createClass({\n      render: function () {\n        return (\n          \u003cdiv className=\"newsList\"\u003e\n            \u003cNewsHeader/\u003e\n            \u003cdiv className=\"newsList-newsItems\"\u003e\n              {_(this.props.items).map(function (item, index) {\n                return \u003cNewsItem key={item.id} item={item} rank={index + 1}/\u003e;\n              }.bind(this)).value()}\n            \u003c/div\u003e\n          \u003c/div\u003e\n        );\n      }\n    });\n\n    module.exports = NewsList;\n    ```\n\n 1. Create a new JS file: /js/NewsListTest.js.\n    ```javascript\n    var $ = require('jquery');\n    var NewsList = require('./NewsList');\n    var React = require('react');\n\n    $.ajax({\n      url: '/json/items.json'\n    }).then(function (items) {\n      React.render(\u003cNewsList items={items}/\u003e, $('#content')[0]);\n    });\n    ```\n\n 1. Create a new CSS file: /css/NewsList.css.\n    ```css\n    .newsList {\n      background: #f6f6ef;\n      margin-left: auto;\n      margin-right: auto;\n      width: 85%;\n    }\n    ```\n\n 1. Create a new HTML file: /html/NewsList.html.\n    ```html\n    \u003c!DOCTYPE html\u003e\n    \u003chtml\u003e\n      \u003chead\u003e\n        \u003cmeta charset=\"utf-8\"\u003e\n        \u003ctitle\u003eNewsList\u003c/title\u003e\n        \u003clink href=\"../css/NewsHeader.css\" rel=\"stylesheet\"\u003e\n        \u003clink href=\"../css/NewsItem.css\" rel=\"stylesheet\"\u003e\n        \u003clink href=\"../css/NewsList.css\" rel=\"stylesheet\"\u003e\n        \u003clink href=\"../css/app.css\" rel=\"stylesheet\"\u003e\n      \u003c/head\u003e\n      \u003cbody\u003e\n        \u003cdiv id=\"content\"\u003e\u003c/div\u003e\n        \u003cscript src=\"../build/js/NewsListTest.js\"\u003e\u003c/script\u003e\n      \u003c/body\u003e\n    \u003c/html\u003e\n    ```\n\n 1. Start Watchify.\n     ```bash\n    watchify -v -o build/js/NewsListTest.js js/NewsListTest.js\n    ```\n\n 1. Start the HTTP server if necessary.\n    ```bash\n    http-server -p 8888\n    ```\n\n 1. Visit [http://localhost:8888/html/NewsList.html](http://localhost:8888/html/NewsList.html). You should see the following.\n\n    \u003cimg src=\"img/NewsListHeaderItems.png\" width=\"270\"\u003e\n\n[Previous](#newslist) \u0026middot; [Next](#newslist-more)\n\n---\n\nNewsList More\n---\n 1. Update the JS.\n    ```javascript\n    var NewsList = React.createClass({\n      // ...\n\n      getMore: function () {\n        return (\n          \u003cdiv className=\"newsList-more\"\u003e\n            \u003ca className=\"newsList-moreLink\" href=\"https://news.ycombinator.com/news?p=2\"\u003eMore\u003c/a\u003e\n          \u003c/div\u003e\n        );\n      },\n\n      render: function () {\n        return (\n          \u003cdiv className=\"newsList\"\u003e\n            ...\n            {this.getMore()}\n          \u003c/div\u003e\n        );\n      }\n    ```\n\n 1. Update the CSS.\n    ```css\n    .newsList-more {\n      margin-left: 40px; /* matches NewsItem rank and vote */\n      margin-top: 10px;\n      padding-bottom: 10px;\n    }\n\n    .newsList-moreLink {\n      color: black;\n      font-size: 10pt;\n      text-decoration: none;\n    }\n    ```\n\n 1. Refresh the browser. You should see the following.\n\n    \u003cimg src=\"img/NewsListMore.png\" width=\"136\"\u003e\n\n    You have now implemented the HN item list in React.\n\n    \u003cimg src=\"img/NewsList@2x.png\" width=\"532\"\u003e\n\n[Previous](#newslist-header-and-items) \u0026middot; [Next](#hacker-news-api)\n\n---\n\nHacker News API\n---\n 1. Create a new JS file: /js/app.js.\n    ```javascript\n    var _ = require('lodash');\n    var $ = require('jquery');\n    var NewsList = require('./NewsList');\n    var React = require('react');\n\n    // Get the top item ids\n    $.ajax({\n      url: 'https://hacker-news.firebaseio.com/v0/topstories.json',\n      dataType: 'json'\n    }).then(function (stories) {\n      // Get the item details in parallel\n      var detailDeferreds = _(stories.slice(0, 30)).map(function (itemId) {\n        return $.ajax({\n          url: 'https://hacker-news.firebaseio.com/v0/item/' + itemId + '.json',\n          dataType: 'json'\n        });\n      }).value();\n      return $.when.apply($, detailDeferreds);\n    }).then(function () {\n      // Extract the response JSON\n      var items = _(arguments).map(function (argument) {\n        return argument[0];\n      }).value();\n\n      // Render the items\n      React.render(\u003cNewsList items={items}/\u003e, $('#content')[0]);\n    });\n\n    ```\n\n 1. Create a new HTML file: /html/app.html.\n    ```html\n    \u003c!DOCTYPE html\u003e\n    \u003chtml\u003e\n      \u003chead\u003e\n        \u003cmeta charset=\"utf-8\"\u003e\n        \u003ctitle\u003eHacker News\u003c/title\u003e\n        \u003clink href=\"../css/NewsHeader.css\" rel=\"stylesheet\"\u003e\n        \u003clink href=\"../css/NewsItem.css\" rel=\"stylesheet\"\u003e\n        \u003clink href=\"../css/NewsList.css\" rel=\"stylesheet\"\u003e\n        \u003clink href=\"../css/app.css\" rel=\"stylesheet\"\u003e\n      \u003c/head\u003e\n      \u003cbody\u003e\n        \u003cdiv id=\"content\"\u003e\u003c/div\u003e\n        \u003cscript src=\"../build/js/app.js\"\u003e\u003c/script\u003e\n      \u003c/body\u003e\n    \u003c/html\u003e\n    ```\n\n 1. Start Watchify.\n    ```bash\n    watchify -v -o build/js/app.js js/app.js\n    ```\n\n 1. Start the HTTP server if necessary.\n    ```bash\n    http-server -p 8888\n    ```\n\n 1. Visit [http://localhost:8888/html/app.html](http://localhost:8888/html/app.html).\n\n    You have now implemented the [HN front page](https://news.ycombinator.com) in React.\n\n[Previous](#newslist-more)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbaxtergu%2Freact-hn","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbaxtergu%2Freact-hn","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbaxtergu%2Freact-hn/lists"}