React.js Frequently Faced Problems

Samer Buna - Feb 20 '18 - - Dev Community

At jsComplete, we manage a slack account dedicated to helping code learners get unstuck. We receive some interesting problems every now and then but most of the asked questions are for common problems. I am creating this resource to write detailed instructions for the common problems beginner React.js learners usually face so that I can refer them to here instead of typing it over and over.


1 — Not starting a component name with a capital letter

A React component must have a name which starts with a capital letter.

If the component name does not start with a capital letter, the component use will be treated as a built-in element such as a div or span.

For example:



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


Enter fullscreen mode Exit fullscreen mode

If you try to render <greeting />, React will ignore the above and you will get a warning:



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


Enter fullscreen mode Exit fullscreen mode

The bigger problem here is when you decide to name your component button or img. React will ignore your component and just render a vanilla HTML button or img tag.

Note how the “My Awesome Button” was not rendered above and React just rendered an empty HTML button element. React will not warn you in this case.

2 — Using single quotes instead of back-ticks

Strings created with back-ticks (`...`) are different from strings created with single quotes ('...').

On most keyboards, the back-tick (`) character can be typed using the key above the tab key.

We create a string using back-ticks when we need to include dynamic expressions inside that string (without resorting to string concatenation).



`This is a string template literal that can include expressions`

'This is just a string, you cannot include expressions here'


Enter fullscreen mode Exit fullscreen mode

Let’s say you want a string that always reports the current time: 

“Time is ...”



// Current time string
const time = new Date().toLocaleTimeString();

// When using regular strings (single or double quotes),
// you need to use string concatenation:
'Time is ' + time

// When using back-ticks,
// you can inject the time in the string using ${}
`Time is ${time}`


Enter fullscreen mode Exit fullscreen mode

Also, when using string literals (with back-ticks), you can create a string that spans multiple lines:



const template = `I

CAN

SPAN

Multiple Lines`;


Enter fullscreen mode Exit fullscreen mode

You can’t do that with regular strings.


3— Using React.PropTypes

The PropTypes object was removed from React. It used to be available as React.PropTypes but you cannot use that anymore.

Instead, you need to:

  1. Add the new prop-types package to your project: npm install prop-types
  2. Import it: import PropTypes from 'prop-types'

Then you can use it. For example: PropTypes.string.

If you incorrectly use React.PropTypes, you’ll get errors like:



TypeError: Cannot read property 'string' of undefined


Enter fullscreen mode Exit fullscreen mode

4 — Not using the right versions of what a tutorial is using

When watching or reading content about coding and following up with the examples they present, make sure that you are using correct versions of the tools the content is using. Usually, using the latest version of each tool is a safe bet, but if the content is a bit old you might run into some deprecation issues.

To be safe, stick with the major versions for the used tools. For example, if the tutorial is using React 16, don’t follow up using React 15.

This is especially important for Node.js as well. You will face major problems if you use an older version of Node. For example, if you’re following along with some tutorial that uses Object.values and you are using Node 6.x, that method did not exist back then. You need Node 7.x or higher.


5— Confusing functions with classes

Can you tell what's wrong with the following code?



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


Enter fullscreen mode Exit fullscreen mode

The code above is invalid because inside the body of a JavaScript class you don’t have the freedom of doing just about anything. You can only define methods and properties using limited syntax.

This is a bit confusing because the {} used in the class syntax looks like the plain-old block scope, but it’s not.

Inside a function-based component, you DO have the freedom of doing just about anything:



// Totally Okay:

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


Enter fullscreen mode Exit fullscreen mode

6 — Passing numbers as strings

You can pass a prop value with a string:



<Greeting name="World" />


Enter fullscreen mode Exit fullscreen mode

If you need to pass a numeric value, don’t use strings:



// Don't do this
<Greeting counter="7" />


Enter fullscreen mode Exit fullscreen mode

Instead, use curly braces to pass an actual numeric value:



// Do this instead
<Greeting counter={7} />


Enter fullscreen mode Exit fullscreen mode

Using {7}, inside the Greeting component, this.props.counter will have the actual numeric 7 value and it will be safe to do mathematical operations on that. If you pass it as “7” and then treat it as a number, you might run into unexpected results.


7 — Forgetting that another app instance is still using the same port

To run a web server, your need to use a host (like 127.0.0.1) and a port (like 8080) to make the server listen for request on a valid http address.

Once the web server is running successfully, it has control over that port. You cannot use the same port for anything else. The port will be busy.

If you try to run the same server in another terminal, you’ll get an error that the port is “in use”. Something like:



Error: listen EADDRINUSE 127.0.0.1:8080


Enter fullscreen mode Exit fullscreen mode

Be aware that sometimes a web server might be running in the background or inside a detached screen/tmux session. You don’t see it, but it is still occupying the port. To restart your server, you need to “kill” the one that’s still running.

To identify the process that’s using a certain port, you can either use a command like ps (and grep for something about your app) or if you know the port number you can use the lsof command:



lsof -i :8080


Enter fullscreen mode Exit fullscreen mode

8 — Forgetting to create environment variables

Some projects depend on the existence of shell environment variables in order to start. If you run these projects without the needed environment variables, they will try to use undefined values for them and will potentially give you some cryptic errors.

For example, if a project connects to a database like MongoDB, chances are it uses an environment variable like process.env.MONGO_URI to connect to it. This allows the project to be used with different MongoDB instances in different environments.

To locally run the project that connects to a MongoDB, you have to export a MONGO_URI environment variable first. For example, if you have a local MongoDB running on port 27017, you would need to do this before running the project:



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


Enter fullscreen mode Exit fullscreen mode

You can grep the project source code for process.env to figure out what environment variables it needs in order to work correctly.

9— Confusing curly braces {} with parentheses ()

Instead of:



return { 
  something();
};


Enter fullscreen mode Exit fullscreen mode

You need:



return ( 
  something();
);


Enter fullscreen mode Exit fullscreen mode

The first one will try (and fail) to return an object while the second one will correctly call the something() function and return what that function returns.

Since any <tag> in JSX will translate to a function call, this problem applies when returning any JSX.

This problem is also common in arrow functions’ short syntax.

Instead of:



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


Enter fullscreen mode Exit fullscreen mode

You need:



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


Enter fullscreen mode Exit fullscreen mode

When you use curly braces with an arrow function, you are starting the scope of that function. The short syntax of arrow functions does not use curly braces.


10 — Not wrapping objects with parentheses

The curly braces vs. parentheses problem above is also confusing when you want to create a short arrow function that returns a plain-old object.

Instead of:



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


Enter fullscreen mode Exit fullscreen mode

You need:



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


Enter fullscreen mode Exit fullscreen mode

Without wrapping the object in parentheses, you would not be using the short syntax. You will actually be defining a label for a string!

This is common inside the updater function of the setState method because it needs to return an object. You need to wrap that object with parenthesis if you want to use the short arrow function syntax.

Instead of:



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


Enter fullscreen mode Exit fullscreen mode

You need:



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


Enter fullscreen mode Exit fullscreen mode

11 — Not using the right capitalization of API elements and props

It’s React.Component, not React.component. It’s componentDidMount, not ComponentDidMount. It’s usually ReactDOM, not ReactDom.

Pay attention to the API capitalization that you need. If you use incorrect capitalization, the errors you’ll get might not clearly state what the problem is.

When importing from react and react-dom, make sure that you’re importing the correct names and what you’re using is exactly the same as what you’re importing. ESLint can help you point out what is not being used.

This problem is also common in accessing component props:



<Greeting userName="Max" />

// Inside the component, you need 
props.userName


Enter fullscreen mode Exit fullscreen mode

If, instead of props.userName, you incorrectly use props.username or props.UserName, you will be using an undefined value. Pay attention to that, or better yet, make your ESLint configuration point these problems out as well.


12— Confusing the state object with instance properties

In a class component, you can define a local state object and later access it with this:



class Greeting extends React.Component { 
  state = { 
    name: "World", 
  };

  render() { 
    return `Hello ${this.state.name}`;
  }
}


Enter fullscreen mode Exit fullscreen mode

The above will output “Hello World”.

You can also define other local instant properties beside state:



class Greeting extends React.Component { 
  user = { 
    name: "World", 
  };

  render() { 
    return `Hello ${this.user.name}`;
  }
}


Enter fullscreen mode Exit fullscreen mode

The above will also output “Hello World”.

The state instance property is a special one because React will manage it. You can only change it through setState and React will react when you do. However, all other instance properties that you define will have no effect on the rendering algorithm. You can change this.user in the above example as you wish and React will not trigger a render cycle in React.


13 — Confusing <tag/> with </tag>

Don’t misplace the / character in your closing tags. Admittedly, sometimes you can use <tag/> and other times you need </tag>.

In HTML, there is something called a “self-closing tag” (AKA void tag). Those are the tags representing elements that do not have any children nodes. For example, the img tag is a self-closing one:



<img src="..." />

// You don't use <img></img>


Enter fullscreen mode Exit fullscreen mode

A div tag can have children, and so you use opening and closing tags:



<div> 
  Children here...
</div>


Enter fullscreen mode Exit fullscreen mode

The same applies to React components. If the component has children content, it might look like this:



<Greeting>Hello!</Greeting>

// Notice the position of the / character.


Enter fullscreen mode Exit fullscreen mode

If the component does not have children, you can write it with open/closing tags or just a self-closing tag:



// 2 valid ways

<Greeting></Greeting>

<Greeting />

// Notice how the / character moves based on whether the element 
// is self-closing or not


Enter fullscreen mode Exit fullscreen mode

The following use is invalid:



// Wrong

<Greeting><Greeting />


Enter fullscreen mode Exit fullscreen mode

If you misplace the / character, you will get errors like:



Syntax error: Unterminated JSX contents


Enter fullscreen mode Exit fullscreen mode

14 — Assuming import/export will just work

The import/export feature is an official feature in JavaScript (since 2015). However, it’s the only ES2015 feature that is not yet fully supported in modern browsers and the latest Node.

The popular configuration of a React project uses Webpack and Babel. Both allow the use of this feature and compile it down to something all browsers can understand. You can only use import/export if you have something like Webpack or Babel in your flow.

However, having import/export in your React bundled app does not mean that you can just use them anywhere you want! For example, if you’re also doing server-side rendering through the latest Node, things will not work for you. You will most likely get an “unexpected token” error.

To have Node understand import/export as well (which is something you need if you use them on the front-end and you want to do SSR as well), you will have to run Node itself with a Babel preset (like the env preset) that can transpile them. You can use tools like pm2, nodemon, and babel-watch to do so in development and have Node restart every time you change something.


15 — Not binding handler methods

I saved this one for last because it’s a big one and a very common problem.

You can define class methods in a React component and then use them in the component’s render method. For example:



class Greeting extends React.Component { 
  whoIsThis() { 
    console.dir(this); // "this" is the caller of whoIsThis 
    return "World"; 
  }

  render() { 
    return `Hello ${this.whoIsThis()}`; 
  }
}

ReactDOM.render(<Greeting />, mountNode);


Enter fullscreen mode Exit fullscreen mode

I used the whoIsThis method inside the render method with this.whoIsThis because inside render, the this keyword refers to the component instance associated with the DOM element that represents the component.

React internally makes sure that “this” inside its class methods refers to the instance. However, JavaScript does not bind the instance automatically when you use a reference to the whoIsThis method.

The console.dir line in whoIsThis will correctly report the component instance because that method was called directly from the render method with an explicit caller (this). You should see the Greeting object in the console when you execute the code above:

However, when you use the same method in a delayed-execution channel, such as an event handler, the caller will no longer be explicit and the console.dir line will not report the component instance.

See the code and output (after clicking) below.

In the code above, React invokes the whoIsThis method when you click on the string, but it will not give you access to the component instance inside of it. This is why you get undefined when we click the string. This is a problem if your class method needs access to things like this.props and this.state. It will simply not work.

There are many solutions for this problem. You can wrap the method in an inline function or use the .bind call to force the method to remember its caller. Both are okay for infrequently-updated components. You can also optimize the bind method by doing it in the constructor of the class instead of in the render method. However, the best solution to this method is to enable the ECMAScript class-fields feature (which is still stage-3) through Babel and just use an arrow function for the handlers:



class Greeting extends React.Component { 
  whoIsThis = () => { 
    console.dir(this); 
  }

  render() { 
    return ( 
      <div onClick={this.whoIsThis}> 
        Hello World 
      </div> 
    ); 
  }
}


Enter fullscreen mode Exit fullscreen mode

This will work as expected:

That’s all for now. Thanks for reading.


Check out my Learn React.js by Building Games book:

I also have a few other books that might interest you:

This article was originally published here

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .