Giter Club home page Giter Club logo

the-road-to-learn-react's Introduction

⛔️ Deprecated

This is the old version of The Road to React with React class components and without React Hooks. Check out the new The Road to React which teaches React Hooks.

The Road to learn React [Book]

Official repository for The Road to learn React. If you want to leave a review, please do it on Amazon or Goodreads.

Translations of the book into Leanpub

The Road to learn React is also available in other languages. Thanks for all translators for their awesome work!

Updates, Help and Support

Contribute

You can help to improve the book by opening Issues and Pull Requests (PR).

You can open up any PR that corrects spelling or explains a certain lesson with more detail. When writing such a technical book, you get fast blind on what needs more explanation and on what is already explained well.

In addition, you can open Issues when you run into problems. In order to make the fix for the Issue as easy as possible, please provide a couple of details such as error log, screenshot, which page of the book it happened, your node version (command line: node -v) and a link to your own repository. Not all of these details are mandatory, but most of them help to fix the Issue and to improve the book.

Thanks a lot for your help!

the-road-to-learn-react's People

Contributors

brentguf avatar emmanuelstalling avatar gunayanil avatar hieutran106 avatar hoppy-kamper avatar jaroldwong avatar jonathascarrijo avatar kenwithee avatar leftium avatar lex111 avatar m-mansoor-ali avatar mattcruzz avatar miguelpayet avatar misacorn avatar mvanio avatar mwiens91 avatar nhuntwalker avatar nicoder avatar pboto avatar pierreturnbull avatar robphoenix avatar romerorocha avatar rwieruch avatar snitin4260 avatar sudo-plz avatar taintedzodiac avatar tsvecak avatar tyler-po avatar tyleri avatar willhumphreys avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

the-road-to-learn-react's Issues

Refer to "test" rather than "it" in Jest example code ?

Overview

In the "Snapshot Tests with Jest" section use is made of the Jest function it.

Background

I wanted to know a bit more about that function and so I went to read the Jest doco.

It seems that the primary naming of that function is now test and so searching / browsing for it in the doco isn't productive (http://facebook.github.io/jest/docs/en/api.html#testname-fn)
.

Suggestion

I wonder whether the relevant sample code should be altered to make use of 'test' rather than 'it' ?

Another option would be to reference the dual names in the text of the book but that seems to me to producing clutter.

I appreciate there may be other reasons it should be left as it is but I would be happy to submit a PR if it was thought to be a good idea.

SORTS[sortKey] is not a function

I have the same code that you have written and when i run the tests it fails at TABLE yet my application works just fine and I don't get any errors in the console.

Unidirectional Data Flow chapter (pg 33) - explanation on wrapping onClick functions with a function

Suggestion to expand the explanation of this paragraph:

As you can see the onDismiss() method in the onClick function gets enclosed by another function.
Only that way you can sneak in the objectID property. Otherwise you would have to define the
function outside. However, by using an ES6 arrow function you can inline it.

To add the following:

The handler needs to be a function. When passing this.onDismss(item.object), it will execute on render and isn’t a function anymore but the return value of onDismiss. We have to wrap it in another function to be able to pass the item.objectID.

We could define the function somewhere outside too and only pass the function:

const onHandleDismiss = () => this.onDismiss(item.objectId) 

and then use it in the onClick:

onClick={onHandleDismiss}

But in the end it has to be a function. When executing the onDismiss on render already, it isn't a function anymore.

As an example, try this code instead:

<button
    onClick={this.onDismiss(item.objectID)}
    type="button"
>

The onClick will no longer work, because as mentioned earlier if you don't enclose it within a function, the objectID cannot be passed.

This code will run on app load:

<button
    onClick={console.log(item.objectID)}
    type="button"
>

This code will run only when onClick is triggered:

<button
    onClick={() => console.log(item.objectID)}
    type="button"
>

Feedback

Hi Robin, just finished the book, thanks for working on this, it was easy to follow and I feel confident in starting a new app from scratch in the coming days. The exercises at the end of each section were very rewarding e.g. implement fontawesome sorting icons with the classnames package.

I wish there was a little more on testing. Maybe another implementation example, say, after a component is refactored. It would help a student implement and update their own future changes.

Thanks again

Explain JS filter function

Pasted below is our Slack discussion on this matter:

Question

On page 35, when we define the function isNotId(item), how do we have access to item? Looks like we get access from our map loop. Also, it’s interesting that we don’t have to call isNotId with parenthesis inside of our updatedList, because it is a function. Please explain.

Response

Thanks for coming up with this! Indeed, it would be better to add more explanation to it.

The JavaScript built-in filter function (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) takes a function as input. The function has access to each value in the filtered list, because it iterates over the list. So it could be: this.state.list.filter(function isNotId(item) { return item.objectID !== id; }); in the first step. But the book already applies the second step where the function gets extracted and only passed into .filter(isNotId).

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter

Tests pass but display console log errors

Test Suite, Tests and Snapshots all correctly pass but terminal shows multiple console log errors.
console.error node_modules/fbjs/lib/warning.js:36 Warning: Failed prop type: The prop value is marked as required in Search, but its value is undefined. in Search (at App.test.js:26

console.error node_modules/fbjs/lib/warning.js:36 Warning: Failed prop type: The prop onChange is marked as required in Search, but its value is undefined. in Search (at App.test.js:26)

console.error node_modules/fbjs/lib/warning.js:36 Warning: Failed prop type: The prop onSubmit is marked as required in Search, but its value is undefined. in Search (at App.test.js:26)

console.error node_modules/fbjs/lib/warning.js:36 Warning: Failed prop type: The prop onClick is marked as required in Button, but its value is undefined. in Button (at App.test.js:42)

console.error node_modules/fbjs/lib/warning.js:36 Warning: Failed prop type: The prop onDismiss is marked as required in Table, but its value is undefined. in Table (at App.test.js:64)

All packages listed in the book have been installed.

Introduction to asynchronous JS

In chapter 3, between Fetching Data and ES6 Spread Operators, add a small introduction chapter for Asynchronous JavaScript with Promises where Promises and the native fetch API are briefly explained. Even though it was already used in the Fetching Data, it should be a nice recap for people who are not too familiar with it.

Anyone wants to make a PR for it? :)

npm install vs npm install --save

In Chapter 1, Under Node and NPM Intro:

Command Line
npm install react
The installed package will automatically appear in a folder called node_modules/ and will be listed
in the package.json file next to your other dependencies

https://github.com/the-road-to-learn-react/the-road-to-learn-react/blob/master/manuscript/chapter1.md#node-and-npm-1

As per npm docs:

To add an entry to your package.json's dependencies:

npm install <package_name> --save

I think the explanation will be listed in the package.json file next to your other dependencies is misleading as one will have to use --save option to do that.

Warning in Test in Chapter 4

Here is my code.

I am getting a warning when testing my App at the beginning of the Testing chapter:

 PASS  src/App.test.js
  ✓ renders without crashing (45ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 totalTime:        1.008s
Ran all test suites related to changed files.
Watch Usage
 › Press p to filter by a filename regex pattern.
 › Press t to filter by a test name regex pattern.
 › Press q to quit watch mode.
 › Press Enter to trigger a test run.
  console.error node_modules/fbjs/lib/warning.js:33
    Warning: Can only update a mounted or mounting component. This usually means you called setState, replaceState, or forceUpdate on an unmounted component. This is a no-op.

    Please check the code for the App component.

For some reason is says I am setting the state before the component is mounted. I found the setState() that triggered is the warning is the one from fetchSearchTopStories()

  fetchSearchTopStories(searchTerm, page = 0) {
    fetch(`${PATH_BASE}${PATH_SEARCH}?${PARAM_SEARCH}${searchTerm}&${PARAM_PAGE}${page}&${PARAM_HPP}${DEFAULT_HPP}`)
      .then(response => response.json())
      .then(result => this.setSearchTopStories(result))
      .catch(e => this.setState({error: e}));
  }

although it is specifically called in componentDidMount()

  componentDidMount() {
    const {searchTerm} = this.state;
    this.setState({searchKey: searchTerm});
    this.fetchSearchTopStories(searchTerm);
  }

when I comment fetchSearchTopStories() in componentDidMount() the warning does not appear.
It's "only" a warning, not an error but I was just wondering if I did something wrong and if I'm the only one with that warning. I did add the isomorphic-fetch but I don't think it is connected to that anyways.

Cannot read property 'ReactCurrentOwner' of undefined

If you have started to read the ebook before the 4th edition was released, but grabbed the 4th edition recently (which uses React 16), you may see the following command line error message when executing your Jest tests for the first time:

FAIL  src/App.test.js
  ● Test suite failed to run

    TypeError: Cannot read property 'ReactCurrentOwner' of undefined

      at node_modules/react-test-renderer/cjs/react-test-renderer.development.js:621:36
      at Object.<anonymous> (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:8254:3)
      at Object.<anonymous> (node_modules/react-test-renderer/index.js:6:20)
      at Object.<anonymous> (src/App.test.js:3:26)
          at <anonymous>
      at process._tickCallback (internal/process/next_tick.js:188:7)

Test Suites: 1 failed, 1 total
Tests:       0 total
Snapshots:   0 total
Time:        0.656s

You need to upgrade your project to React 16. Check your package.json if you run an old version of React. If you do so, type the following on the command line:

npm i -g npm-check-updates
npm-check-updates -u
npm install

It is a global npm module that can be used to update your dependencies, such as react or react-dom, in your package.json file. I should’ve mentioned it in the first place, for people grabbing the new edition who have an old React version installed.

See also #84

Define onSearchChange in Client- or Server-Side Search chapter

In the chapter Client- or Server-Side Search, I realize that onSearchChange has not been defined in the API refactoring of the component, thus making it so that the input value for the Search component was not able to be changed through the browser. I had to Command-F through the ebook for the last time it was defined, and that was back in Interactions with Forms and Events. It should be included in either the Fetching Data chapter that starts the API section of the book, or in the Client- or Server-Side Search, when it becomes necessary to change the value of the input box.

code line breaks with \ confuse people

Excellent book, thanks very much for putting this together. I'm working through it and on page 84/85 where you deal with the pagination / Hacker news API the book mentions the following code:

<div className="interactions">
    <Button onClick={() => this.fetchSearchTopstories( searchTerm, page + 1\ )}>
        More
    </Button>
</div>

I was getting an error here, I think due to the \ after the page variable is increased by 1. I.e. should be:

<Button onClick={() => this.fetchSearchTopstories( searchTerm, page + 1 )}>

If I am indeed correct, I hope that helps someone.

Page 21 broken code snippet?

function isSearched(query) {
    return function(item) {
        return !query || item.title.toLowerCase().indexOf(query.toLowerCase()) !== -\
1;
        }
}

"Syntax error: Unterminated regular expression (26:81)"

Use of default parameter for fetchSearchTopstories

Hello,

first of all, thank you for you book! It's clear, gets to the point without overwhelming details, perfect starting point to the React world.

As a feedback, I would suggest to use default parameter in function fetchSearchTopstories in chapter Paginated Fetch. You can then omit the second argument in the following calls.

Couldn't get preventDefault() to work

Having gone through the book (as of the version available 21st December, as I was using a printed copy based on 884f31e)

I tried a number of things to get the event.preventDefault() line in onSearchSubmit to work - I understand from this answer on SO that it's because of the Native event/Synthetic event difference. Fundamentally though, wherever I had it, it still reloaded the page on submit. (Chrome & Firefox)

Ended up using an external package wrapper for this to make it work (Works perfectly after a simple npm install react-prevent-default, but this feels like a workaround rather than a fix) - I wondered if there's a longer explanation/route to get that preventDefault() working as written, or if I've missed something on it?

(This might be out of date, judging by the number of commits i've seen here, but worth flagging in any case, as it seems like a thing people might trip up on.)

Clarify JSX when using list.map

Regarding this section: https://github.com/the-road-to-learn-react/the-road-to-learn-react/blob/master/manuscript/chapter1.md#complex-javascript-in-jsx

The following returns an Array of HTML elements in JSX.

{list.map(function(item) {
          return <div>{item.title}</div>;
        })}

I think it should be clarified/mentioned that this returns an Array of HTML elements which React automatically loops through and renders each element in the array.

In other words, the reader should know that React can work with this:

{
[
<h1>H1 header</h1>,
<h2>H2 header</h2>,
<h3>H3 header</h3>
]
}

Problem with 'ref a dom element' example when testing ?

Summary

When following the "Ref a DOM Element" section I found that my code would run perfectly well (and move the focus to the search box as intended) when running the server but would crash and burn when attempting to run tests.

Nature of fault

When running the tests I got this stack trace

    TypeError: Cannot read property 'focus' of undefined

      at Search.componentDidMount (src/App.js:54:8)
      at commitLifeCycles (node_modules/react-dom/cjs/react-dom.development.js:8798:24)
      at commitAllLifeCycles (node_modules/react-dom/cjs/react-dom.development.js:9967:9)
      at HTMLUnknownElement.callCallback (node_modules/react-dom/cjs/react-dom.development.js:540:14)
      at invokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:219:27)
      at HTMLUnknownElementImpl._dispatch (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:126:9)
      at HTMLUnknownElementImpl.dispatchEvent (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:87:17)
      at HTMLUnknownElementImpl.dispatchEvent (node_modules/jsdom/lib/jsdom/living/nodes/HTMLElement-impl.js:36:27)
      at HTMLUnknownElement.dispatchEvent (node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:61:35)
      at Object.invokeGuardedCallbackDev (node_modules/react-dom/cjs/react-dom.development.js:579:16)
      at invokeGuardedCallback (node_modules/react-dom/cjs/react-dom.development.js:436:27)
      at commitRoot (node_modules/react-dom/cjs/react-dom.development.js:10071:9)
      at performWorkOnRoot (node_modules/react-dom/cjs/react-dom.development.js:11003:42)
      at performWork (node_modules/react-dom/cjs/react-dom.development.js:10952:7)
      at requestWork (node_modules/react-dom/cjs/react-dom.development.js:10861:7)
      at scheduleWorkImpl (node_modules/react-dom/cjs/react-dom.development.js:10744:11)
      at scheduleWork (node_modules/react-dom/cjs/react-dom.development.js:10706:12)
      at scheduleTopLevelUpdate (node_modules/react-dom/cjs/react-dom.development.js:11177:5)
      at Object.updateContainer (node_modules/react-dom/cjs/react-dom.development.js:11215:7)
      at node_modules/react-dom/cjs/react-dom.development.js:15232:19
      at Object.unbatchedUpdates (node_modules/react-dom/cjs/react-dom.development.js:11086:12)
      at renderSubtreeIntoContainer (node_modules/react-dom/cjs/react-dom.development.js:15231:17)
      at requestWork (node_modules/react-dom/cjs/react-dom.development.js:10861:7)
      at scheduleWorkImpl (node_modules/react-dom/cjs/react-dom.development.js:10744:11)
      at scheduleWork (node_modules/react-dom/cjs/react-dom.development.js:10706:12)
      at scheduleTopLevelUpdate (node_modules/react-dom/cjs/react-dom.development.js:11177:5)
      at Object.updateContainer (node_modules/react-dom/cjs/react-dom.development.js:11215:7)
      at node_modules/react-dom/cjs/react-dom.development.js:15232:19
      at Object.unbatchedUpdates (node_modules/react-dom/cjs/react-dom.development.js:11086:12)
      at renderSubtreeIntoContainer (node_modules/react-dom/cjs/react-dom.development.js:15231:17)
      at Object.render (node_modules/react-dom/cjs/react-dom.development.js:15296:12)
      at Object.it (src/App.test.js:28:24)
      at Promise.resolve.then.el (node_modules/p-map/index.js:46:16)
      at process._tickCallback (internal/process/next_tick.js:109:7)

The code being referenced at the top of the stack (src/App.js:54:8) looks like this

componentDidMount() {
this.input.focus();
}

In addition to that (and other similar) stack traces the following rather opaque error messages were shown below the test summary

  console.error node_modules/react-test-renderer/cjs/react-test-renderer.development.js:5533
    The above error occurred in the <Search> component:
        in Search (at App.js:239)
        in div (at App.js:238)
        in div (at App.js:237)
        in App (at App.test.js:19)

    Consider adding an error boundary to your tree to customize error handling behavior.
    Visit https://fb.me/react-error-boundaries to learn more about error boundaries.

... and ...

  console.error node_modules/react-test-renderer/cjs/react-test-renderer.development.js:5533
    The above error occurred in the <Search> component:
        in Search (at App.test.js:37)

    Consider adding an error boundary to your tree to customize error handling behavior.
    Visit https://fb.me/react-error-boundaries to learn more about error boundaries.

Resolution

I rewrote the relevant code as follows

  componentDidMount() {
    if(this.input) {
      this.input.focus();
    };

and that resolves the issue in test while allowing the server to run as intended.

Suggestion

Should the example code be altered to adopt the usage shown above ?

enzyme adapter config needed

I had to add additional configuration to the enzyme test unit. I was using React build 16, so had to use:

import Adapter from 'enzyme-adapter-react-16';

configure({ adapter: new Adapter() });

To enable enzyme unit tests.

Object spread operator is not explained on first use

When using the array spread operator for the first time, its use is mentioned and a link provided to the ES6 array spread operator. When the object spread operator is used for the first time however (pages 52-53) it might be worth mentioning its use and a similar link provided to a definition. The use of the object spread was in the following example:

results: { ...this.state.results, [query]: { hits: updatedHits, page } }

The page linked to for the array spread operator (https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Spread_operator) does mention object spread but it only appears as a brief mention and does not explain its use or syntax. Suggested link is [https://github.com/sebmarkbage/ecmascript-rest-spread] but I'm not familiar enough to know if it is the definitive one.

Filtering list on onSearchChange behaves differently

On Chapter "Basics in React" - "Interactions with Forms and Events"

I followed this chapter and created the search functionality, it works fine: When I type the search term, the list updates and when I hit backspace and remove the search terms, also the list updates.

But when I made this modification: Instead of updating the searchTerm on onSearchChange and adding the filter for the list on render method, I did the filtering in the onSearchChange method and updated the list, similar to how it is done for onDismiss.

    onSearchChange(event) {
	let searchTerm = event.target.value;
	const updatedList = this.state.list.filter(isSearched(searchTerm));
	this.setState({ list: updatedList });
    }
  render() {
    return (
	    <div className="App">
	    <form>
	    <input type="text" onChange={this.onSearchChange} />
	    </form>
	    {this.state.list.map(item =>
        	 <div key={item.objectID}>
        	 <span>
.
.

the list is NOT updating when I hit backspace in the search box and remove the term one by one.

diff

Original, expected behavior:

orig

Any idea why this might be happening?

Failed prop type in jest testing

While running the snapshot tests I get the following warning: The prop 'onClick' is marked as required in Button but its value is undefined.

Using JavaScript ES6 to define functions instead of bind (Suggestion)

This is kind of a follow-up to #9, but I'd like to suggest using ES6 arrow functions to define the functions in App. For example, the following example from the book:

class App extends Component {

  constructor(props) {
    ...
    this.onSearchSubmit = this.onSearchSubmit.bind(this);
  }

  onSearchSubmit() {
    const { query } = this.state;
    this.fetchSearchTopstories(query);
  }

  ...
}

could also be expressed as:

class App extends Component {

  constructor(props) {
    ... // this.onSearchSubmit is not defined here
  }

  onSearchSubmit = () => {
    const { query } = this.state;
    this.fetchSearchTopstories(query);
  }

  ...
}

Even though the official React tutorials use bind, since using ES6 is encouraged, I think it'd be a good idea to incorporate this usage. By the way, I got this idea from the MDN page about arrow functions, which is linked in Chapter 1 on page 11.

More concise still?

Line 332 of Chapter one, "{ list.map((item) =>", the docs referenced at the bottom of the page suggest you can even just do "{ list.map(item =>"? Any reason this wouldn't be preferred?

Thanks for the resource, awesome so far!

Upgrade React 16

The 4th edition of the book uses React 16. If you started to read the book in a previous edition, but grabbed the recent 4th edition, you need to upgrade your dependencies in your package.json file. The easiest way to do so is executing the following commands on the command line in your project:

npm i -g npm-check-updates
npm-check-updates -u
npm install

It is a global npm module that can be used to update your dependencies, such as react or react-dom, in your package.json file. I should’ve mentioned it in the first place, for people grabbing the new edition who have an old React version installed.

See also #83

Spanish Translation

Hi! I finished the book a couple of days ago and I really liked it. I just saw that there are some translations of the book (Chinese, Portuguese, etc) and I was wondering if I could do the same, but for a Spanish translation. How I would go about it?

Confusion about the spread operator (suggestion)

In the function setSearchTopstories, the following code is used to update state.results with a new list of hits for the searchKey:

this.setState({
  results: { ...this.state.results, [searchKey]: { hits: updatedHits, page } }
});

I was slightly confused about this usage of the spread operator, because the linked MDN page says "Note that the spread operator can be applied only to iterable objects." After looking it up myself, I found out that the spread operator for objects is actually not officially in ECMAScript yet, but React has already incorporated it, so it's a React-specific feature for now (not ES6). It might be a good idea to add a note about this in the text for others who get confused about this.

"react-scripts: not found" after install of "isomorphic-fetch"

I'm logging this is an issue in case it's of some use of to others who encounter the same situation. Unfortunately I didn't make comprehensive notes of all that happened and so it's won't really be a first class issue.

Situation

I was working through "Snapshot Tests with Jest"

As described in the book I ran npm test and I got an error which, it seemed to me, was related to the unsupported fetch method as described in the book. Unfortunately I didn't make a note of the message.

So I did npm install isomorphic-fetch and amended App.js accordingly.

I then found that when I did a npm test I got

foobar@polo /media/poloextra/dev/r2lr/hackernews $ npm test

> [email protected] test /media/poloextra/dev/r2lr/hackernews
> react-scripts test --env=jsdom

sh: 1: react-scripts: not found

so I then tried a yarn start and got a similar result

foobar@polo /media/poloextra/dev/r2lr/hackernews $ yarn start
yarn start v0.16.1
$ react-scripts start
sh: 1: react-scripts: not found
error Command failed with exit code 127.

I

Resolution

After receiving some advice on the slack channel I did a yarn install and then tried a yarn start again. At that point I still got the error shown above so I did a yarn upgrade followed by a yarn start which then worked as I expected.

After that I was able to do a yarn test and that too worked as I would have expected.

Comment

I've no real idea what happened here. It seemed to have been triggered by the installation of isomorphic-fetch but I don't know why. It's probably irrelevant but I wouldn't normally use npm as I would use yarn. I used npm on this occasion as I was following along with the text of the book.

JavaScript Truthfulness

The book relies heavily on JavaScript's concepts of truthfulness. E.g. if (!list.length) is used in favor of if (list.length === 0) or if(someString) is used in favor of if(someString !== ''). It should be explained briefly by using the more verbose version and refactor it to the shorthand version.

An ideal PR would find the chapter where such a condition is used the first split and split it up into the verbose and shorthand version for a brief explanation.

Missing Guide for development setup on Windows

In the book there is only one article linked that gives instructions on how to setup everything on a Mac. Since the author of the book is no Windows user, it is hard to describe a guide on how to setup everything on Windows. Would someone want to write a guest blog post about it which can be referenced for the book?

Use .md extension for chapter files

You could use a .md extension for the chapter files instead of .txt. It's an (undocumented) feature of Leanpub and it greatly improves rendering on GitHub.

Add translated versions of book to README.md

At this point in time, there are various translated versions coming up for the book. Maybe it would be great for all readers from different countries to see all the options in the README.md of the book and the status of each book (e.g. work in progress, done). Anyone wants to help out here? :)

You can find all the translations and their repositories in the organization: https://github.com/the-road-to-learn-react

No 'Access-Control-Allow-Origin' header is present on the requested resource.

At the moment, there is a high likelihood that you run into the following error when building your Hacker News application.

Failed to load https://hn.algolia.com/api/v1/search?query=foo&page=0&hitsPerPage=100: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

I am checking back with Algolia if there is anything to fix it on our side of if there was any change on their side in the first place. algolia/hn-search#106

If there is no solution to this in the long run, I have to change the API to a different one. Otherwise I think a backend proxy could be a solution. Even though I would love if students could still use the official HN API 😢

In the meantime, you could try to replace your requests to Algolia with another API: https://github.com/cheeaun/node-hnapi There you have an up and running Hacker News API server (e.g. https://node-hnapi.herokuapp.com/news?page=3).

Confused about this.setState

In chapter2, it says "By using this.setState you can manipulate the internal component state."

Where does this.setState come from? I don't see it defined anywhere. Is it built into React?

edit: Was able to look it up and read about it here. Might be a good idea to link a resource like this in the book?

On the same page, onSearchChange is also defined like this:
this.onSearchChange = this.onSearchChange.bind(this);

Is there any reason why onSearchChange isn't directly defined inside the constructor?

“overwritten” methods

There are several occurrences of the phrase “methods overwritten” in the book. Shoud it be “methods overridden” instead?

App.js default unit test fails

The default test with jest fails. log below.
My guess is that is related to the fact that the App component fires http requests that returns a promise and that the default test does not handle.

TypeError: Network request failed at XMLHttpRequest.xhr.onerror (/Users/cookies/Documents/programming/learnreact/hackernews/node_modules/whatwg-fetch/fetch.js:408:16) at XMLHttpRequest.callback.(anonymous function) (/Users/cookies/Documents/programming/learnreact/hackernews/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:289:32) at invokeEventListeners (/Users/cookies/Documents/programming/learnreact/hackernews/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:219:27) at invokeInlineListeners (/Users/cookies/Documents/programming/learnreact/hackernews/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:166:7) at EventTargetImpl._dispatch (/Users/cookies/Documents/programming/learnreact/hackernews/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:122:7) at EventTargetImpl.dispatchEvent (/Users/cookies/Documents/programming/learnreact/hackernews/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:87:17) at XMLHttpRequest.dispatchEvent (/Users/cookies/Documents/programming/learnreact/hackernews/node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:61:35) at XMLHttpRequest.abort (/Users/cookies/Documents/programming/learnreact/hackernews/node_modules/jsdom/lib/jsdom/living/xmlhttprequest.js:384:16) at Object.abort (/Users/cookies/Documents/programming/learnreact/hackernews/node_modules/jsdom/lib/jsdom/living/xhr-utils.js:315:13) at RequestManager.close (/Users/cookies/Documents/programming/learnreact/hackernews/node_modules/jsdom/lib/jsdom/living/nodes/Document-impl.js:145:21) at Window.close (/Users/cookies/Documents/programming/learnreact/hackernews/node_modules/jsdom/lib/jsdom/browser/Window.js:316:29) at JSDOMEnvironment.dispose (/Users/cookies/Documents/programming/learnreact/hackernews/node_modules/jest-environment-jsdom/build/index.js:46:19) at Promise.resolve.then (/Users/cookies/Documents/programming/learnreact/hackernews/node_modules/jest/node_modules/jest-cli/build/runTest.js:65:9)

stuck with code at nteraction with forms and events

Hi,

I bought your book. Thanks very much for it.

I'd really like to suggest having a per chapter branch or tag of this hacker news app. So that, like me, if someone gets stuck somewhere they can review what the code should look like at the end of that chapter by fetching that branch or tag in the repo.

I looked online, stackoverflow and the final hacknews app and still can't figure what is wrong here. I'd really appreciate it if you could help me a bit, below is the code and if I click the Dismiss button it cribs saying this Cannot read property 'onDismiss' of undefined

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';

const list = [
  {
    title: 'React',
    url: 'https://facebook.github.io/react/',
    author: 'Jordan Walke',
    num_comments: 3,
    points: 4,
    objectID: 0,
  },
  {
    title: 'Redux',
    url: 'https://github.com/reactjs/redux',
    author: 'Dan Abramov, Andrew Clark',
    num_comments: 2,
    points: 5,
    objectID: 1,
  },
];

class App extends Component {

  constructor(props)
  {
    super(props);
    this.state = {
      list,
    };

    this.onDismiss = this.onDismiss.bind(this); 
  }
  

  onDismiss(id)
  {
    function isNotId(item) { return item.objectID !== id;}
    const updatedList = this.state.list.filter(isNotId);
    this.setState({list: updatedList});
  }

  render() {
    return (
      <div className="App">
        { 
          list.map(function(item) {
          return (
            <div key={item.objectID}>
              <span>
                <a href={item.url}>{item.title}</a>
              </span>
              <span>{item.author}</span>
              <span>{item.num_comments}</span>
              <span>{item.points}</span>
            <span>
              <button type="button" onClick={()=>{this.onDismiss(item.objectID)}}>Dismiss</button>
            </span>
            </div>
          );
        })}
      </div>
    );
  }
}
export default App;

Clarification on isSearched() function on pg 41

Slack Discussion

The Question

I was a bit confused on the significance of the bang operator on the isSearched() function, but someone on the slack channel (Han) quickly cleared that up for me.
The function in question:
const isSearched = searchTerm => item => !searchTerm || item.title.toLowerCase().includes(searchTerm.toLowerCase());

Answer

The ! is there to ensure that when the searchbar is empty it will evaluate to true instead of false, thus when invoked by this function
{ this.state.list.filter(isSearched(this.state.searchTerm)).map(item =>
it will still map through every value even when the searchbar is empty.

Thank you Han for the clarification and Robin for the great book :)

Page 87-89 - ES5 Object.assign()

Let’s do it in JavaScript ES5. Object.assign() and ...
That’s it in JavaScript ES5
it can be used to replace ES5 Object.assign().
etc.

There seems to be a mistake, Object.assign is a new ES6 method (not ES5).

Why is value={query} necessary?

In chapter2, the book says to insert value={query} in this line:
<input type="text" value={query} onChange={this.onSearchChange} />

Why is this necessary? The filtering seems to work without it.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.