📜 ⬆️ ⬇️

Frequent difficulties in working with React.js

Hi, Habr! I present to you the translation of the Samer Buna article "React.js Frequently Faced Problems" .
Do not panic. You're right: there are myriads of web technologies, architectures and frameworks, and a lot of them are under development right now. Remember: everyone who has become a professional web developer started out like you. They studied languages, libraries one at a time, time after time, until they pumped up their skills and working mechanisms.

Web development is now the first trip to the supermarket. On the shelves of hundreds of products that you want to seize. Having become puzzled, it is very easy to be frightened by a huge choice. It will be a mistake to try to learn everything at once, as if you need to be competent everywhere.

In fact, if you concentrate on one thing, for example, creating a website in the simplest HTML / CSS / JavaScript without libraries, and then add a framework like React, your path from beginner to professional will be much more convenient and pleasant.
Indeed, it is difficult for newbies to deal with simple things that an experienced developer doesn't even pay attention to. This article is intended to make out the popular mistakes and difficulties that most React learners face.

1 - Component name with a lowercase letter


The React component must have a name beginning with a capital letter. If this is not the case, the component will be treated as inline: div or span .
')
For example:

class greeting extends React.Component { // ... } 

Try to pass the framework (render) <greeting /> - React will give the error:

 Warning: The tag <greeting> is unrecognized in this browser. If you meant to render a React component, start its name with an uppercase letter. 

Which tells us: “Start with a capital letter, is it difficult or something?”.

* And never call the component button , img and other tags. React will simply ignore them and render as a bare HTML tag. *

image

2 - Using single quotes instead of reverse apostrophes


Strings are created with back quotes ( `...` ) (orig. “Back-ticks”), and they differ from ordinary single quotes ( '...' ).

On most keyboards, reverse apostrophes can be set by pressing the key above Tab.

That is what we use when we need to insert a dynamic expression into a string, not using a line break and subsequent concatenation.

 `         ` '     ' 

Let's imagine a situation: you need to display a message about how much time is “Time: ...”

 //       const time = new Date().toLocaleTimeString(); //    ,  //    'Time is ' + time //    ,  //    ${} `Time is ${time}` 

Also, inside the reverse apostrophes, you can make a line break.

 const template = `      `; 

With the usual single quotes you do not crank this.

3 - Using React.PropTypes


The PropTypes object has been removed from React. It's just not there, and you need to get used to it. But now:


It works now. Example: PropTypes.string .

If there is still a line with React.PropTypes in the code, then you will get an error
on the head:

 TypeError: Cannot read property 'string' of undefined 

4 - Using the versions described in the tutorial


When you view or read programming lessons and follow the examples from there, make sure you have the lesson version installed. Usually the use of the latest versions of modules is safe, but the tutorial is obsolete. As a result, you will definitely encounter errors. Conversely, if the tutorial uses React 16 , do not be lazy to replace your 15th version.

This is especially important for Node.js. Bugs with old versions are there on every corner. For example, in Node 7.x , Object.values ​​was removed, so it would be easier to upgrade than correct your code on Node 6.x

5 - Confusion between functions and classes


Can you tell where the error is in this code?

 class Numbers extends React.Component { const arrayOfNumbers = _.range(1, 10); // ... } 

The code is incorrect, because inside the body of the JavaScript class you have almost no rights to anything . You can only declare methods and properties through a limited syntax.

This is really confusing, because {} curly braces in the syntax of the class look like a familiar block structure, but it is not.

If you want freedom in action, use components based on functions:

 const Number = (props) => { const arrayOfNumbers = _.range(1, 10); // ... }; 

6 - Numbers as strings


You can pass properties using the string:

 <Greeting name="World" /> 

If you need to pass a number, do NOT write them in quotes:

 //   ! <Greeting counter="7" /> 

Instead, insert them into braces:

 <Greeting counter={7} /> 

Using {7} inside the Greeting component, you can get your number using this.props.counter and you can do mathematical operations with it absolutely safely. Incorrect use of the “7” can lead to unpredictable consequences.

7 - Two applications on one port


To start the web server, you need a host (for example 127.0.0.1) and a port (for example 8080) to make the server listen for requests at the correct http address.

As soon as the server starts, it has full control over the port. You will no longer be able to turn on your iron on the same port. He will be busy (Port, not iron!).

Try running the same server from another terminal. You will most likely get the error “Used”:

 Error: listen EADDRINUSE 127.0.0.1:8080 

Sometimes it turns out that the port is used in the background . You do not see him, but he interferes with life. In such situations, it is advantageous to “kill” the one that occupies the precious port:

 lsof -i :8080 

8 - Environment Variables


Some projects depend on the existence of environmental variables (original “Environmental variables”). If you start the application without the necessary variables, it will try to start using undefined values ​​( undefined ), and, of course, this will lead to critical errors.

For example, if a project is connected to a MongoDB database, then environment variables of the type process.env.Mongo_URI will be useful in order to safely connect to the database. They can also be quickly changed depending on the situation (is it not necessary to connect another database).

To run a project with MongoDB locally, you first need to export the MONGO_URI variable. Required, if the database works, say, on port 27017, do it before you run the application:

 export MONGO_URI = "mongodb://localhost:27017/mydb" 

9 - Figure {} or round () brackets


Instead

 return { something(); }; 

Write

 return ( something(); ); 

The first example will try (and it will not work) to return an object, while the second will be able to call the function something () and return what the function should return.

Since the <tag> in the JSX syntax will call a function, this problem applies to any JSX code.

It also applies to switch functions (orig. “Arrow functions”). Instead

 const Greeting = () => { <div> Hello World </div> }; 

Write

 const Greeting = () => ( <div> Hello World </div> ); 

* Just remember: in ES6, curly brackets for the arrow functions are not needed! *

10 - Failing to enclose objects in parentheses


Finish the topic from the previous paragraph. It is easy to get confused, referring to the switch functions for the same, to return a normal object.

Instead

 const myAction = () => { type: 'DO_IT' }; 

Write

 const myAction = () => ({ type: 'DO_IT'}); 

Without wrapping an object in parentheses, you will never be able to achieve what a short syntax was invented for.

To fix, consider a similar ready-made example:

 this.setState(prevState => ({ answer: 12 })); 

11 - Using the wrong letter in methods


React.Component , but not React.component . componentDidMount , not ComponentDidMount . Generally ReactDOM , but not ReactDom .

Pay attention to how various methods are written, because, having made such an error, you can really spend time with it, and then you will be ashamed of yourself. Try ESLint , it will help to track such errors.

Often errors occur when accessing properties:

 <Greeting userName="Max" /> //   props.userName 

For example, if instead of props.userName you enter props.username or props.UserName , then the value undefined will be returned.

12 - Errors in the application of the state object


In component classes, you can declare a local state object, and later get its value through this :

 class Greeting extends React.Component { state = { name: "", }; render() { return `, ${this.state.name}` } } 

The program will display “, ” .

Instead of state, you can use any object name. For example:

 class Greeting extends React.Component { user = { name: "", }; render() { return `, ${this.user.name}` } } 

Will output the same thing.

However, there is a difference. state is a special object managed by React. You can change the value through setState and React will react to it. Such a trick will not work with the example code above, although you can still use it if you do not want to see the reaction.

13 - Porridge in <tag /> and </ tag>


Do not forget to put forward slash / when you close the tag. And yes, sometimes you need <tag /> and sometimes </ tag> .

HTML has self-closing tags (orig. “Self-closing tag”). These are elements without "children." For example, img refers to this:

 <img src="..." /> //    <img></img> 

You can put as many others as you want into the div tag, so you need to open and close it either:

 <div>  ... </div> 

The same rule applies to React components.

 <Greeting>Hello!</Greeting> //  ,    

However, if he does not have “children,” you can still open / close him, and you can also use the self-closing tag:

 // 2   <Greeting></Greeting> <Greeting /> 

Example of misuse:

 //    <Greeting><Greeting /> 

From that you should see an error:

 Syntax error: Unterminated JSX contents 

14 - Expecting import / export to “just earn”


The import / export capability has been officially supported by JavaScript since 2015. However, this is the only one from ES2015 that is not fully supported by all browsers and the latest version of Node .

Often projects on React create with Webpack and Babel . They allow you to compile your code into what all browsers will understand. Therefore, it is better to use import / export together with Webpack and Babel .

To make Node understand import / export, which is sometimes necessary, for example, in cases when you use them on the front (frontend) and have SSR ( Server-Side Rendering - server-side rendering, isomorphic application ). To do this, you need the presence of Babel in the Node itself. For ease of development, I advise you to connect something from pm2 , nodemon , babel-watch .

15 - Bind Issues


You can declare class methods in React components, and then include them in the render method. For example:
 class Greeting extends React.Component { whoIsThis() { console.dir(this); // "this"   whoIsThis return "World" } render() { return `Hello ${this.whoIsThis()}` } } ReactDOM.render(<Greeting />, mountNode); 

I used the whoIsThis method inside render 'a using this.whoIsThis , because in this case this refers to the DOM element (that is, the component itself).

React is trying to verify this. However, JavaScript does not even try to automatically link (orig. “Bind”) this and the whoIsThis method.

Test it with examples. The console.dir line in whoIsThis will print the Greeting object, because the method was called directly from the render'a:

image

However, when you use a class method in a place that will not be called immediately, for example in an event handler (orig. “Event handler”), console.dir will not print what was expected:

image

In the example above, React calls the whoIsThis method only after clicking on a string, which will not give you access to the component from the inside. That is why you get undefined .

This is a preface that often a problem arises when trying to get this.props or this.state from a class method. It just won't work. There are many ways to solve. You can wrap the method in a function or use .bind to make the method remember the one who calls it. You can also do bind in the class constructor , not in render 'e.

Still, the best solution would be to use features from ECMAScript (this is stage-3 ) for classes through Babel , and to write pointer functions in handlers:

 class Greeting extends React.Component { whoIsThis = () => { console.dir(this); } render() { return ( <div onClick={this.whoIsThis}> Hello World </div> ); } } 

It will work as expected:

image

That's all. Thank you for reading.

Source: https://habr.com/ru/post/347458/


All Articles