Category Archives: React

react js

useMemo

ref – https://www.w3schools.com/react/react_usememo.asp

Use useMemo

To fix this performance issue, we can use the useMemo Hook to memoize the expensiveCalculation function. This will cause the function to only run when needed.

We can wrap the expensive function call with useMemo.

The useMemoHook accepts a second parameter to declare dependencies. The expensive function will only run when its dependencies have changed.

In the following example, the expensive function will only run when count is changed and not when todo’s are added.

Containment (component inside a component)

functional components are defined like so:

After importing it, you can call the component like in this example:

Some components don’t know their children ahead of time.

We recommend that such components use the special children prop to pass children elements directly into their output:

This lets other components pass arbitrary children to them by nesting the JSX:

Furthermore, you can use property extraction by using prop as an object and declaring the property that we’re looking for:

Creating a bridge from react native to native iOS

  • https://reactnative.dev/blog/2017/03/13/introducing-create-react-native-app
  • https://reactnative.dev/docs/next/communication-ios

We first install create-react-native-app module:

npm install -g create-react-native-app

We then create the app:

Look at the directory. You’ll see the iOS folder with its xcode files.

Running the iOS simulator

npm run ios

It’ll take a few minutes for the app to build. You’ll see a terminal pop up with the title “Metro.node launcher package”. Then your simulator will start and the app will install and run.

Implementing the app

Features

We first create a file called ImageBrowserApp.js

Its a class component, where we simply display an image.
We render this image through JSX Image tag.
If no image URLs are given, we simply return ‘No Images Available’.

In index.js, make sure we use AppRegistry to register this component like so:

In your App.js, you can use it like so:

App.js

When you export it to iOS, it will look like this:

In the native iOS side, we can also instantiate ImageBrowserApp to be used as a view.
This is made possible when we registered the component with the name ImageBrowserApp

So in AppDelegate, we simply create a RCTRootView and initialize the module name to ImageBrowserApp.
Then we add it to the rootView.

iOS side

AppDelegate.h

AppDelegate.m

Server side rendering (isomorphic React apps) – Data

Server

We start the server side.

At the GET verb of any url..we already have code where we store initial state in our redux. This time, let’s start it off by fetching data.

We create an initial state object, when store fetched data into an array called repositoryNames. Remember that in order to fetch in Node, we need to either use axios, or node-fetch package.

server.js

Notice thunk. Redux Thunk is a middleware that lets you call action creators that return a function instead of an action object. That function receives the store’s dispatch method, which is then used to dispatch regular synchronous actions inside the function’s body once the asynchronous operations have been completed.

Once that is done, we create our store, and place it in Provider component. Then place that into StaticRouter within our appMarkup.

This is so that we can inject it into our HTML component.

We then return this HTML component in our response object to the client.

Client Side

We do the same and apply thunk for the client. Since we already have the store and initial app state, it will match up with what the server has.

Before in App.js, where we declare our mapping to props with initialText and changeText handler, we dispatch a very simple Action object with a literal object like so:

which then get passed to reducers/index.js to be processed like so. The initialText is a simple string so we can do this:

But now, we use action objects defined in actions/index.js for more complicated procedures:

Thus, now in Home.js, we declare mapDispatchToProps with the action object getRepositoryNames:

ref – https://reactjs.org/docs/hooks-effect.html

That way, we can use getRepositoryNames inside of Home component. Since Home is a functional component, we use useEffectuseEffect runs after every render!

By default, it runs both after the first render and after every update. Instead of thinking in terms of “mounting” and “updating”, you might find it easier to think that effects happen “after render”. React guarantees the DOM has been updated by the time it runs the effects.

This is the basic case in our example.

Hence we check for props repositoryNames. If its valid, we’ll display it. If it isn’t, we’ll fetch the data so it can be rendered.

Also, useEffect has a nifty feature where it can look at a state variable. If that state changes, it will run the effect. In our case, it would fetch. Hence, I put two use cases of this:

1) value changes after each click. useEffect will run every time the button is clicked because onClick updates value everytime.
2) value changes once after clicks. So useEffect will run the first time, value updates, runs second time, and that’s it.

Event Bubbling and Capture

ref –

  • https://gomakethings.com/what-is-that-third-argument-on-the-vanilla-js-addeventlistener-method-and-when-do-you-need-it/
  • https://medium.com/@vsvaibhav2016/event-bubbling-and-event-capturing-in-javascript-6ff38bec30e

Event Bubbling is the event starts from the deepest element or target element to its parents, then all its ancestors which are on the way to bottom to top. At present, all the modern browsers have event bubbling as the default way of event flow.

So the event goes from button, all the way to the top global object.

use event.stopPropagation() to stop at a certain level:

addEventListener useCapture parameter (Event Capturing)

You may sometimes see a third argument on the addEventListener() method.

That third argument, true? That’s called useCapture.

The reason for this parameter is because certain events, like focus, don’t bubble.

If you wrote your event listener like this, the event would never fire.

So, what exactly does useCapture do?

The useCapture argument, when set to true, tells the addEventListener() method to capture events that happen in the parent.

Instead of the event bubbling from the originating element up to each parent, the event listener starts at the parent and works its way down. This allows you to use event delegation on non-bubbling events.

Event Capturing is the event starts from top element to target element. Modern browser doesn’t support event capturing by default but we can achieve that by code in JavaScript.

Full View of Event Flow

Every event flow has three phase:

  1. Event Capturing
  2. Event Target
  3. Event Bubbling

Mosh React HTTP tutorial 2

Expected Errors

Expected errors are client errors. For example, if we have an invalid id, the server will give us a 404 not found.
For example,

If you try to do a HTTP delete something providing a parameter id, you’ll get a 404 error because the server api endpoint is expecting it as part of its interface.

Unexpected Errors

Unexpected errors are network errors, server errors, db errors. The response status will be less than 400, and larger than 500.

Conceptually, we’d handle errors like so.
First, we update our local UI right away…in what we call an optimistic error handling. We are optimistic that the server update will be successful so we update our local UI right away. Then, we do the server update after. This gives a nice UI flow.

Notice we have a reference to the posts. This is so that in case the server update has an error, we can revert back to our original state by reassigning it.

So, when an expected error occurs (such as invalid ID), we see the alert, then we’ll see that it inverts back to the original state list. This is good and simple way to handle it.

This is the result of an unexpected error. For example, we give it a weird URL where it does not reach a server. In normal circumstances, this would either be a server down, db down, or no internet (Network down) error. In which, you’ll probably get a 500 status. For now, we simply log it.

Improving it with Axios

The problem with our previous approach is that we need global handling. But we cannot possibly do try/catch for all the different places that we need error handling. Hence, we install Axios to do this:

npm install axios@0.18.1

Axios has an interceptor where we check to see what kind of error it has. That way, all errors from using axios will have to go through this interceptor.

The first parameter is success. In our case, we don’t need to deal with it, so just give it a null. The second parameter is a reference to a callback for when we receive an error. Exactly what we need. So we give it a callback function with an error parameter.

We check to see if the error has a response object. If it does, look at its status. If it’s 400 or more, and less than 500, it means it’s an expected error. This is when you didn’t supply the correct parameters or didn’t satisfy the endpoint interface. In which case, simply just return the error.

However, if it’s an unexpected error, we get to alert it. As you can see, we write this just once. All the other places where we use axios to execute HTTP requests will come here when there’s an error. Let’s try testing it at componentDidMount:

As you can see, by giving it an erroneous URL, it goes through logging error in the interceptor.

Extracting a Reusable Http Service

However, we have superfluous code in our app module. We need to refactor.

Create a services folder, then create httpService.js file. We move all the interceptor logic in here. Also, we wrap Axios’s functionality.

Then in App.js, we import Axios and replace all axios operations with our http module:

Extract config Module

Create config.json file
We put constants and configuration strings there:

Then in our App.js, we import it, and replace previous global constants.

Using Toast

Now we use Toast library to put some UI animation behind our error handling.
npm install Toastify@4.1.0

In our App.js, right below our React Fragment, we put the ToastContainer. The point is to put our handlers that have try/catch and axios actions within this ToastContainer. Any kind of errors that bubble out from the JSX will be captured by this ToastContainer.

App.js

We go to our http module where we throw out errors and put the needed error messages:

httpService.js

As long as you remember to import the toast function from ‘react-toastify’, you can use the Toast UI animation.

Mosh React HTTP tutorial 1

Tutorial material code

code source

Download the folder and go to HTTP-APP folder.

npm install
npm start

You’ll see the project’s basic UI.

Install Axios: npm install axios@0.18.1

Open a browser and enter http://jsonplaceholder.typicode.com/posts
You’ll see that it returns a bunch of test data. We’ll be using this in our app.

In our code, we’re going to use Axios to fetch data from this url. Axios returns a promise object. This promise object holds the
result of an async operation.

When we log the promise object at that instnace, it will say pending, but it resolves when it succeeded, and fails when it rejects. A promise object has function then() which can get the results of this async operation, but this is the old (es5) way.

The modern es6 way is to use async/await. We put await in front of our async operation like so:

Make sure you match it up with an async keyword in front of our function. Execution does not continue within the function until the response receives data. However, execution does asynchronously continue on to process other code outside of the function.

When data is received and the promise object resolves, execution continues from the await line. You can log the response object and see all the data. We then destructure and extract data we need from this response object.

Finally, we then set the data onto the state so the code can reflect the updated UI

App.js

Adding Data

Now, using our previous knowledge, lets implement handle add. By analyzing the object from our previous get, we know that each object has properties title and body.

We first create a literal object with properties title and body.

We then use axios’s post function. First parameter specifies the URL.

Second specifies the object we’re sending.

Finally, when it finishes posting the object to the server, it will return that object back to let us know it succeeded.

We should update our local UI by creating a new array with this updated post, and fill in the rest with this.state.posts.
Then set the array back to state.

So essentially, what’s happening is that we get all the data first. After some time, the Promise object resolves via await and returns us a response object with the data. We populate the basic UI with it.

We then add a post by clicking the ‘Add’ button. We write a handler for that button and use axios.post to tell the backend to add our data. Once the Promise object resolves via await, it returns the post we want to add.

If we were to add three times, we notice it in our UI. Click on ‘Network’ and we see three posts.

Click on the first one and notice request method. Usually the request method is GET, POST, PUT, DELETE..etc. The reason why there is an OPTION there is because Chrome is preflighting the request to look for CORS headers.

If the request is acceptable, it will then send the real request. If you’re doing this cross-domain, you will simply have to deal with it or else find a way to make the request non-cross-domain.

If you click on the header, you’ll see the request payload that’s being sent.

When your request is successful, you’ll see the response object that the server sends back to you.

Updating the Data

Optimistic Updates with Error handling

If we were to simply add, update, or delete from the server, and then update our UI to reflect those actions, there is a small wait time on the UI. This is because we’re waiting for the server to update us with a response, and then to update our UI.

In order to remedy this issue, we flip them. We

1) update the UI first
2) Then execute the async operation.

If all goes well like 99% of the time, great. If not, we can revert.

The revert process is:

1) create a reference to the original state

2) update the UI
3) try/catch on the async operation. When you catch the exception, make sure you setState back to the original

Thus, when we run the app, we see the original list. When we delete, it deletes the local right away.

Our simulated error makes the alert box appear. Once we click on the ‘ok’ button, our code setState property posts back to the original.

Mosh React Tutorial (part 14)

1) mosh-react-tut-refactor-table-head

2) mosh-react-tut-extract-body

Refactoring Movies Table

So in movies.jsx, we see a lot of code in our render function. Let’s pull out table, as it makes up the bulk of our JSX.

In components, we create controlled MoviesTable.jsx. Basically, in order to extract code, we to first figure out what we want the refactoring to look like.
A closer look tells us that the table code involves three things:

1) the array that shows the data
2) the delete function
3) the sort function
4) Sort column that specifies the column text and sort order

All these handler objects and belong in movies.jsx. So as a controlled component, we should not have state, and simply show data via the props object.
Thus we need to make sure that in movies, we pass them in.

movies.jsx

So in MoviesTable, we extract them from the prop object and refactor like so:

Extracting Table Header from Movies Table

Notice MovieTable’s render is huge. Let’s extract the table header out.
We want to create a table header component in the render where we do something like this:

We had a string of paths and names in literal strings. So we first create an array to depict this:

We already have sortColumn object and onSort function in props, so we can directly pass it into TableHeader component.
thus, when we write our TableHeader component, we get the columns as an array and display their text. When they get clicked, we raise the sort function, which takes the prop object, and use the sortColumn property. Finally, it uses the passed in prop’s onSort function.

In src, components, common, create TableHeader.jsx file:

TableHeader.jsx

MoviesTable.jsx

Extracting Body

We also need to extract the boy from MoviesTable. The movies array is passed via the props data. We map through it and display tr for each movie.

For each tr (movie), we need to display the properties of the movie. In JS, we can do object[property] to access the value of the property in an object. However, if there are nested objects, we cannot go object[property.anotherProperty]. Therefore, “genre.name” won’t work. However, we can use lodash for this:

It takes the object ‘item’, then it gives the property path column.path. It will down into the object with the properties path and return you the value.

Notice that our output only has text data. Our ‘delete’ button is nowhere to be seen.
Hence, let’s add the delete button into our columns array.

MoviesTable.jsx

So now when we render this cell, we have to check for column.content. If its exists, its a delete button and returns JSX elements. If it doesn’t, then property is path and returns text and we use lodash for it:

For each row of data, we have to go through each column’s path (title, genre.name, numberInStock…) in order to display data.
The renderCell function to takes the item, column and display it (text or button…etc) as table data.

data is array of movies
columns is our defined array of property names, labels, and key/content JSX.

Hence, as go through each row, we must extract data like so:

TableBody.jsx

Let’s also update our handleDelete function in movies.jsx:

movies.jsx

MoviesTable.jsx