Home >Web Front-end >JS Tutorial >React.js: What I've Learned from My First Project

React.js: What I've Learned from My First Project

Linda Hamilton
Linda HamiltonOriginal
2025-01-26 06:29:11309browse

Originally published to Medium for JavaScript in Plain English on April 2, 2023

Over the past several weeks, I have begun learning another highly sought-after skill in the web development world: React.js. Feeling at least somewhat comfortable with a lot of things in JavaScript, and at the behest of some of my mentors, I figured this was the most logical step to take to reach my career goals. In this article, I will share with you some things I’ve learned about it as a rookie.

For some context, I have only worked with Class Components in React, never with Functional Components I will not describe the differences here, since I don’t really know anything about Functional Components now. I will likely write an article someday contrasting the two types. Even at the time I write this article, it's recommended by everyone to use Functional Components, but it still pays to know how Class Components work, since older React projects may use them.

For my first project, I was tasked with building a debt calculator, in which the user can enter the Debt Principal, the Interest Rate, how much they want to pay. There are a few stipulations for these input fields, but you can read about those in the project’s README.md (link the GitHub repo is at the end of the article), or you can try it out yourself to see how it works. Once the user ‘submits’ a payment, a payment history item will appear, giving details about the Principal, Interest, & the Balance. Unless the user pays off the entire debt in the first payment, all input fields except the payment field are disabled when the first payment is made; if the entire debt is paid off, the entire form is disabled, & the user can view the history of the final payment, along with a message that they are debt-free.

I will provide answers to the following questions I had about React while starting to learn about it:

What is React.js, and why should it be used?

How do I start building a React App?

What does a typical component look like?

How can I share info between components?

Can I render things conditionally in React?

How can I deploy a React app?


What is React.js, and why should it be used?

React is a front-end JS library (not a framework ?) ) that makes organizing large-scale projects easier. It was originally developed at Facebook more on that here, & is now maintained, of course, by Meta, which also uses it for Instagram. It is now widely used on many sites across the interwebs, such as Airbnb, BBC, Imgur, & Netflix, among many others.

React code consists of reusable components, which must be located inside the src folder, & whose names must be in CamelCase form. Many components are written in JSX (JavaScript Syntax Extension), which is a kind of mix between HTML & JS. I call these components ‘reusable’ because they have the same structure & different information may be passed to them & displayed on the site. Components can also be written in normal JS. Different information, such as user account information, can then be passed to these components & they will all display in the same way.

How do I start building a React App?

To initialize a React app, enter the following commands into the terminal:

npx create-react-app project-name
cd project-name
npm start

npm start will open the project in your default browser in an empty port.
It usually takes a few minutes for everything to be set up, so maybe do something productive in the meantime, like uploading a silly dance to TikTok, or finding out which Hogwarts House you would be sorted into (yes, I made that quiz).

The official documentation now recommends using a framework to initialize a React app. I have not used one yet, but you can read more about that here.

What does a typical component look like?

Like I mentioned, I have only worked with Class Components so far, so I will only cover those in this article. The components I used for my first project are a bit large to put here, so please see the App.js & the PaymentHistory.jsx files in the src folder in the repository linked at the end of the article to see them in action. Nevertheless, typical Class Component may look like this:

// Import React & ComponentOne:
import React from "react";
import ComponentOne from "./ComponentOne;

class App extends React.Component {
  /* Add props as params here, in case state values 
  are to be shared with another component */
  constructor(props) {
    super(props);

    // Initialize state values:
    this.state = {
      stateValue1: '',
      stateValue2: ''
    }
  }

  // Add some methods:
  changeFontColor = () => {
    // do something
  }
  changeFont= () => {
    // do something
  }

  // Determine what the component should render:
  render() {
    return (
      <div>
        <p key="pgHeader" onClick={this.changeFontColor}>Header</p>
        <p key="pgContent" onClick={this.changeFont}>Content</p>
        <p key="pgFooter">Footer</p>
      </div>
      // Give ComponentOne access to method changeFont by passing it in as a prop:
      <ComponentOne changeFont={this.changeFont} />
    )
  }
}
export default App;

Notice that I added a key value to each

element inside the

. These are not necessarily crucial to the ability of the app to function properly, but it is best practice to include them. A unique key value should be added to each child of a parent element inside return().

Like a normal JS Class, the first thing that should come is the constructor(), followed by super(). If we wish to share, for example, state values or methods from one class to another, we need to pass in props, short for 'properties', as the parameter for both constructor() & super().

Then, we should initialize state values. In my debt calculator project, I needed to use multiple state values to track various amounts of money pertaining to the Payment, Principal, Interest Owed, & Balance, but I also used a couple that determined how or if certain things should be rendered. Here's how I used the isDebtFree state value to enable an input field when it equals false, & disable it when it is true:

npx create-react-app project-name
cd project-name
npm start

As you can see, we can change state values in Class Components by using a setState function. Keep in mind that setState runs asynchronously, so any functionality that requires the updated state values could be put in a callback. However, you should keep these callbacks as simple as possible, or you will end up in the confusing world of 'Callback Hell', so follow the Single-Responsibility Principle as best as you can when creating methods in the component. You should also know that each time state is changed within the component, the component re-renders.
The DOM should not be manipulated directly inside of a method. Doing so is called an 'antipattern'. Notice how I did not access the DOM element directly by setting the disabled attribute inside the method, like so:

// Import React & ComponentOne:
import React from "react";
import ComponentOne from "./ComponentOne;

class App extends React.Component {
  /* Add props as params here, in case state values 
  are to be shared with another component */
  constructor(props) {
    super(props);

    // Initialize state values:
    this.state = {
      stateValue1: '',
      stateValue2: ''
    }
  }

  // Add some methods:
  changeFontColor = () => {
    // do something
  }
  changeFont= () => {
    // do something
  }

  // Determine what the component should render:
  render() {
    return (
      <div>
        <p key="pgHeader" onClick={this.changeFontColor}>Header</p>
        <p key="pgContent" onClick={this.changeFont}>Content</p>
        <p key="pgFooter">Footer</p>
      </div>
      // Give ComponentOne access to method changeFont by passing it in as a prop:
      <ComponentOne changeFont={this.changeFont} />
    )
  }
}
export default App;

Instead, parts of HTML elements in return() should be set to a state value, which could change based on the execution of methods in the component, as I showed you in the code block before the one directly above this paragraph.

One more thing to note is that the component's return() expression should be as short as possible, so avoid putting any type of mathematical expressions there, as well as functionality that is defined here. I made this mistake at first when I tried setting the min & max values in the payment field, which change based on state values, which change when numbers are input into the Principal & Interest Rate fields, & when a payment is made.

I instead made a method for each of these values, then set the min & max values to what these methods returned. The first method below worked, but it is not exactly a good way to do it in React, as, again, the return() part of a component should be as short & easy-to-read as possible.

// Initialize isDebtFree:
// Should go inside the constructor, but left out here for brevity
this.state = {
  // other state values
  isDebtFree: false
  // other state values
}

// Change isDebtFree to true if payment equals the total remaining balance
// This method will be called upon payment submission
updateValues = () => {
  // other stuff
  if (newBalance === 0) {
    this.setState({
      isDebtFree: true
    })
   }
}

// Set the disabled property of an input field to equal isDebtFree:
render() {
  return (
    <input disabled={this.state.isDebtFree} />
  )
}

The method below is more in accordance with the spirit of React:

// DO NOT ACCESS DOM ELEMENTS DIRECTLY INSIDE A METHOD!
updateValues = () => {
  if (newBalance === 0) {
  document.getElementById('payment').disabled = true;
 }
}

How can I share info between components?

As we you can see in the first coding block in this article, I passed a method from one component to another using props. Now, let's look at how this second component could access what we passed to it from App in the first code block above. This is what that part looked like, in case you're too lazy to scroll all the way up to see it:

// You could put math operations directly inside elements in return()...
// ... but this is not the best way
render() {
  return (
    <input
      type="number"
      min={
        this.state.principal / 100 +
            (this.state.principal * Number(this.state.interestRate)) / 100 / 12;
      }
      max = {
        this.state.principal +
            (this.state.principal * Number(this.state.interestRate)) / 100 / 12;
      }
    />
  )
}

Now, in ComponentOne, let's import this method from App & put it to use:

// A BETTER WAY
// Create 2 methods; one returns the min payment possible, the other the max:
getMinPmt = () => {
  let minPmt =
    this.cleanValue(this.state.principal / 100) +
    this.cleanValue(
      (this.state.principal * Number(this.state.interestRate)) / 100 / 12
    );
  let totalBalance =
    this.state.principal +
    this.cleanValue(
      (this.state.principal * Number(this.state.interestRate)) / 100 / 12
    );
  if (totalBalance <= 100 && totalBalance > 0) {
    minPmt = totalBalance;
  }
  return this.cleanValue(minPmt);
};
getMaxPmt = () => {
  let maxPmt =
    this.state.principal + 
    this.cleanValue(
      (this.state.principal * Number(this.state.interestRate)) / 100 / 12
    );
  return this.cleanValue(maxPmt);
};

// Set the min & max values of the input to what the respective method returns:
render() {
  return (
    <input
      type="number"
      min={this.getMinPmt()}
      max={this.getMaxPmt()}
    />
  )
}

So, after accessing the changeFont method, we call it when the h1 we render is clicked.

Can I render things conditionally in React?

Yes! React is all about conditionally rendering things. There are a couple ways to do it. You can do this with a method, then set the value of an element in return() to equal that. So, let's use the debt calculator example again. Let's say we want to display the message "You're debt-free!" if the state value of the balance is 0, & a button that prompts the user to make another payment if the balance is over 0. There are a couple ways we could do this.

Let's first set the value of this element to what a method returns, based on the conditions:

npx create-react-app project-name
cd project-name
npm start

Using a method may be advantageous, as it allows us to keep the return() more concise. We can also add more-complex conditions, just like in a normal JS function.

We can also use a ternary operator inside of return() to accomplish the same thing:

// Import React & ComponentOne:
import React from "react";
import ComponentOne from "./ComponentOne;

class App extends React.Component {
  /* Add props as params here, in case state values 
  are to be shared with another component */
  constructor(props) {
    super(props);

    // Initialize state values:
    this.state = {
      stateValue1: '',
      stateValue2: ''
    }
  }

  // Add some methods:
  changeFontColor = () => {
    // do something
  }
  changeFont= () => {
    // do something
  }

  // Determine what the component should render:
  render() {
    return (
      <div>
        <p key="pgHeader" onClick={this.changeFontColor}>Header</p>
        <p key="pgContent" onClick={this.changeFont}>Content</p>
        <p key="pgFooter">Footer</p>
      </div>
      // Give ComponentOne access to method changeFont by passing it in as a prop:
      <ComponentOne changeFont={this.changeFont} />
    )
  }
}
export default App;

If logic is simple enough to be expressed with a ternary operator & it's still easily read, go ahead and use one; otherwise, it's always acceptable to use a method.

For example, if you have simple conditions & want to display nothing if conditions are not met, you can do this:

// Initialize isDebtFree:
// Should go inside the constructor, but left out here for brevity
this.state = {
  // other state values
  isDebtFree: false
  // other state values
}

// Change isDebtFree to true if payment equals the total remaining balance
// This method will be called upon payment submission
updateValues = () => {
  // other stuff
  if (newBalance === 0) {
    this.setState({
      isDebtFree: true
    })
   }
}

// Set the disabled property of an input field to equal isDebtFree:
render() {
  return (
    <input disabled={this.state.isDebtFree} />
  )
}

If this.state.totalBalance strictly equals 0, then the message will display. If not, then nothing will display.

How can I deploy a React app?

I deployed my first React project through Netlify, to which I granted access to the project's GitHub repository. Before deploying, you should run npm run build to build the app for production to the build folder. It bundles React in production mode and optimizes the build for best performance. You can update the site as you normally would another site.

In your index.html file, you may need to change a few paths, including the favicon url, in . You should only need to replace '%PUBLIC_URL%' with ./. Look for instructions like this in :

Image description


So there were a few things I learned while building my first React project. My knowledge about React does not run all that deep yet, so if you have any suggestions for me or any information to add, please add a comment. If you found it helpful, please leave a nice comment or leave a reaction of some kind, & if you think someone else could benefit from reading this, pass it on to them.

Thanks for reading!

Full React.js Documentation
My First Project in Action
Project's GitHub Repository

The above is the detailed content of React.js: What I've Learned from My First Project. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn