😎React Js (Udemy - John Smilga)

https://www.youtube.com/watch?v=4UZrsTqkcW4&t=38s

What is create-react-app

create-react-app is an npm package that helps to create react apps.

Creating the react apps from scratch can be a long process because we need to

  • configure it

  • setup web pack and babel ( that packages our code and transforms it into browser understandable code)

  • create react app also includes (otherwise we need to configure ) web server

  • create react app also includes testing library (which we can't easily implement it ourselves).

Hence, create-react-app provides out of box configuration for all the above things.

What is npx?

We will be using npx with create-react-app. The npx is Node Package Runner, it

  • Downloads the latest version of create-react-app template every time

  • So it's not dependant on when you last installed create-react-app

  • In fact, the create-react-app is never installed on our machines, the npx pulls the latest version of create-react-app

  • npx comes with npm 5.2 or higher

Starting steps after create-react-app

Delete all the files in the src folder except index.js

How to connect index.js (starting point of the app) with index.html?

index.html will have the code

Our entry point to the app isindex.js because the goal is to insert index.js code into the above div placed at index.html.

circle-info

Notice that the first letter of the function should be captialized. Here Greeting, G is capital.

Also, we must always return something from the function. Otherwise, we get an error.

How to insert the index.js into <div id="root"></div>. That is by using ReactDom.render()

JSX

It's a syntactical sugar to make the elements look like HTML but under the hood, it uses React.createElement(). The syntactic difference between HTML and JSX is, in JSX we use camel case, so for example, onclick in HTML will be onClick is JSX. Also, class in HTML will be className in JSX.

React Fragments

The idea of splitting as components

Let's say we have the below code that has a h1 and p. We can split into two componets.

Separate component for p

Practical Tasks

Task 1 : (use state on Array) Remove List Items on click

clear items deletes all and Remove deletes individual item

Task 2 : (use state on Object) Change the message property in the object

Change Message click changes message to Hello World

Task 3 : (use State on numbers) - Bad practice as we are not using callback to update state. Good practice is given below

Task 3 : (Good practice) Why to pass a callback function to update the state?

The above counter example (Task 3) is a bad practice. Let's say we have clicked on increase button but the value increases only after 2 seconds. In this two seconds, how many ever times we press the increase button, the value updates only once after 2 seconds. This is because setValue() is asynchronous and when it get's executed, it takes the global value (at the time of execution). This will be 0 and after 2 seconds, when async function, setValue gets executed this will be looking for global value which is 0 and updates to 1. That's the reason it ignores all the clicks.

The best practice is to use a callback function inside the setValue and pass this value as an argument. Now, the value is bound to the function and always updates internally when clicked and will be displayed after 2 seconds.

circle-info

This above approach of using callbacks to get the value inside of useState can be applied for all 3 tasks above. Some times, when using numbers as state, we definitely need it but in case of array and object useState, it's optional.

UseEffect hook

useEffect runs after every render by default. Every time the state changes the component rerenders and hence the useEffect runs by default.

useEffect by default (no second argumnet)
useEffect by default (no second argumnet)
useEffect if condition (default useEffect just like above)

UseEffect with second argument empty

The useEffect runs only once (first time) when second argument array is empty

UseEffect with dependencies

If we have dependencies in second argument array, then the useEffect runs when that dependency/dependencies change

useEffect dependecies

We can also have multiple useEffects

multiple useEffect hooks

useEffect with clearnup function

Why we need a cleanup function
useEffect cleanup function

Task 4 : (useEffect) Build a github user profiles page

Task

Task 5: Set Loading Or Error before displaying data

&& and || operators

Example of && and ||

An alternate way of writing || using ! and &&

Alternate way of writing || using &&

Problems with Fetch API - Reasons to use axios

  • We need to call then twice (one to get json response and the other one is to get the data). That is because the response.json() gives you the promise and not the data

  • The second problem is the fetch doesn't return 404 error if the user not found. If you modify the URL, then it doesn't consider 404 as an error. We need to manually write a case to check if we get back the data. The network errors are considered as the errors by fetch API and not 404.

    • The solution to this problem

React Forms

Controlled Inputs (As I type I change the state)

In controlled inputs, we'll link up our inputs to the state values by using event.target.value. We don't use useRef hook here

Uncontrolled Inputs

We use useRef for the uncontrolled inputs and not the event.

controlled and uncontrolled inputs (screenshot from cocktail project of John Smilga)

Advantages of Uncontrolled inputs sometimes

  • If we want to focus on the search bar right away when the page loads then we can do it using useRef. Of course we can use controlled inputs and then use useRef as well but instead, we can only use useRef to set the state as well like shown above in the image (commented part)

htmlFor

Use of htmlFor

Submit button

We have two options

  • Either we can add the onSubmit on the form

  • Or we can add onClick on to the button inside the form and make the button type = submit

Just like in JavaScript, in the form handler method, we get access to event by default

By default, when the form is submitted, it refreshes the page. We need to prevent this by using e.preventDefault().

Now, how to access the data inside the inputs

Well, we can set the state values for each input and access them. But when we type something, the state value should be updated using onChange. As and when we type, the state value changes using onChange where the state value gets updated. This is why we call them controlled inputs where the state value is changed based on what we type when onChange is used. onChange is controlling the state updates.

Now that we connected the dots, let's work on a simple task

Task 6: Add form data to an array and display it

Handling multiple inputs

You see we're setting two useStates to two values, one for name and one for age. What if there are multiple inputs like more than 7 or 8 in the form which will generally be the case. We could technically have those many useStates but it would be better if we manage a single useState using an object.

Finally, we can make use of name attribute in the jsx

Before we see how to handle multiple inputs, let's get to know what name attribute in HTML input tag does

The name attribute indicates the name of the input. Let's say we have 10 input elements so when we give a unique name to each one, we can then use this later to identify which input we are talking about. The event (in handleSubmit) will have access to the name using e.target.name. That's the beauty. Let's now see how we can handle multiple inputs.

useRef hook - Uncontrolled inpyts

In uncontrolled inputs, we'll not link up our inputs to the state values.

Though we could do many things with useRef, the most popular one is to target the dom element and set up uncontrolled input similar to how we do in vanilla JS

useRef works a lot like useState but there are a few differences.

Though the useRef and useState both preserves the values between the renders, the useRef doesn't cause a re-render like useState. One of the most use cases of useRef is targeting the dom element.

Think like we are getting back the HTML element on a form submit just like we get when we do document.querySelector(). You can then get the value or whatever. Imagine document.querySelector() is same as useRef current.

useRef

useRef is mostly used to focus on the input element when the page loads

Task 7 : Focus on input when form loads using useRef

2nd use case of useRef

To display the previous state value

2nd usecase of useRef
more on useRef

useReducer hook

Similar to useState (in fact, the useState is built on useReducer) that helps to set the state and we can use this instead of useState when the app grows big and we need a certain way to update the state. Consider having many state values that need to change on updating something then this is the way to go. If I click on a button and if 10 individual setState calls must be done then useReducer is better than useState.

Let's use useReducer to replicate this. Though the useReducer is not necessary here with such a small number of states, I would like to show how useReducer works.

  • First define useReducer that takes two args, reducer and intital state

  • The useReducer will give back state and dispatch (can be any names). Destructure them

  • Define the arguments of useReducer which are reducer and intitial state

Add, remove operations of useReducer

useContext hook

Used for avoiding props drilling. If intermediate components don't need a specific prop, we some times need to still pass it to that component in order to pass the prop further. We can make use of useContext hook for that

React.createContext() will give access to Provider and Consumer. We earlier used to use Consumer but now we use useContext hook for the consumption of the provided value by Provider.

Provider

Provider

Consumer

Consumer - useContext

Setup errors of workspace

The browser page does not auto-refresh after making any changes in the component

To the root path, add .env file and inside it, add FAST_REFRESH=false

Interesting Articles

Do we need to do event delegation in react?

No, react do performance optimizations for us.

React does perfomance optimizations so we don;'t need to worry

Build and Deploy

Add CI =

Add CI= in package.json

build in package.json (add CI)

Custom hook

Let's say we have a functionality to fetch the data from an API. So it would have these functionality

  • Have state value to store the fetched data

  • An async function to fetch the data from the API and store in the state above

  • useEffect which calls the function above

So useEffect calls the async function --> async function that gets data from external API and stores in the state.

So the full component would look like this

The data fetch part is this one

This part would be common to fetch the data. Let's say we have to fetch from other API as well. We then need to repeat this above code (variables would be different).

So to keep the code DRY, we can put the above functionality in a function and call that function every time and reuse. But the problem with that is, it would not re render if data changes. So in this case to reuse the functionality and also re render the useEffect hook when data changes, we can use Custom hook.

The difference between a function and custom hook is

  • Custom hook re-renders any changes just like a useEffect hook

  • It will start with use keyword

So let's turn the above component to use a custom hook called useFetch(). This useFetch takes a URL parameter so that we can make use of this hook to fetch different APIs. This hook will return the things whatever the main component needs.

The component would now be

This could not be achieved with normal function as we get error if we use hooks inside normal function. But one thing to keep in mind is, if the function name starts with capital letter then hooks can be used inside that function. Then that function will become a react component.

To better understand the difference between normal function and react custom hook, refer this

PropTypes

PropTypes are used when there are some props missing in data we get back from server. Let's say we have https://course-api.com/react-prop-types-examplearrow-up-right, the last product has missing image and price

If this happens, your entire app will fail and will throw error. Even if 99 products are good and if one product has a missing prop, you will get error and app will not load at all. To counter this, we can use PropTypes and the idea is, if some of the props are missing then we can provide default props.

circle-info

Now I could have explained this in detail like how we implement it, but since this is very rarely used in the code, I would rather refer to John's video on udemy when needed.

Performance Optimization

React is fast by default. But it still provides some hooks so that we can optimize it further in necessary use cases. These hooks are

  • React.memo

  • useMemo

  • useCallback

Just because react provides these, it doesn't mean you need to use them all over the place. They come with a cost of memory and performance, so absolutely if necessary then only use it. Here's an article that explains when and when not to use it

KentCDodds

React Memo

When state or props change in parent, the parent component re-renders. Because of this, even the child component/s re-render which might nor be necessary in some cases.

React memo explained

Wrapped the component in React memo

useCallback

So when count is increased, we didn't want to re-render our child component BigList as the BigList component didn't have count as props. But we do have addToCart function as props in BigList. This function will change every time when count changes as the functions will be re-created when component re-renders hence triggering the child BigList to re-render.

So one reason to use useCallback is to avoid this function (addToCart) re-creation. Once the function doesn't re-create then our react memo will stop re-rendering the child if the parent Index's count value changes.

The second use case of useCallback hook is to address a warning about missing dependencies.

useMemo

useCallback will remember the function (it decides if the function needs to be re-created or not) whereas useMemo is not for a function but for a value. useMemo decides whether a value should be recomputed or not.

circle-check

Last updated

Was this helpful?