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. *

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:
- Add a new prop-types module: npm install prop-types
- We import into the necessary file: import PropTypes from 'prop-types'
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" />
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);
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:

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:

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:
That's all. Thank you for reading.