Categories
JavaScript JavaScript Basics

JavaScript Events Handlers — onblur and onerror

In JavaScript, events are actions that happen in an app. They are triggered by various things like inputs being entered, forms being submitted, changes in an element like resizing, or errors that happen when an app is running, etc.

We can assign event handlers to respond to these events. Events that happen to DOM elements can be handled by assigning an event handler to properties of the DOM object for the corresponding events.

In this article, we will look the onblur and the onerror property.

window.document.onblur

The onblur property let’s set an event handler function to it to handle the blur event, where the object that represents the element that can lose focus has lost focus. For example, we can attach a onblur event listener function by writing the following code:

document.onblur = () => {  
  console.log('Document lost focus.');  
};

After adding the code above, when we click outside the page then ‘ Document lost focus.’ should be logged.

window.document.onerror

The onerror property lets us attach an event handler to handle situations when the error event is triggered.

The error event is triggered when a JavaScript run time error occurs, such as when syntax errors or exceptions are being thrown within handlers occurs. The error event handler can take a parameter that has the ErrorEvent object in this case.

These errors get bubbled up to the window object by default. It’s also fired when a resource, like an image or script element, fails to load. An error event using the Event interface will be passed into the error event handler in this case. These errors do not get bubbled up to the window object, but it can be handled in window.addEventListener with useCapture is set to true which is the third argument of the addEventListener method.

For historical reasons, the arguments that are passed into window.onerror are different from the ones that are passed into element.onerror as well as on error-type window.addEventListener handlers. window.onerror’s error handler function has the following function signature:

window.onerror = function(message, source, lineno, colno, error) { ... }

Where message is the error message, the source is the string of the URL of the script that threw the error. The lineno parameter is a number that has the line number where the error was raised. The colno parameter is a number that has the column number for the line where the error occurred. The error parameter has the Error object. The Error object has the following standard properties:

  • constructor — the function that created the instance’s prototype
  • message — the error message
  • name — the error name

It also has vendor-specific properties. For Microsoft browsers, the Error object has the following additional properties:

  • description — the error description, which is similar to message
  • number — the error number

For Mozilla browsers, the following additional properties are added to the error object:

  • fileName — the path to the file that raised the error
  • lineNumber — the line number that raised the error
  • columnNumber — the column number of the line that raise the error
  • stack — the stack trace of the error

If an error event handler is passed into the second argument of the window.addEventListener method, then the function signature of the event handler is significantly different. It should have one event parameter which is the ErrorEvent, so the function signature should be the one below:

window.addEventListener('error', function(event) { ... })

The ErrorEvent inherits all the properties from the Event object plus the following properties are included:

  • message — a read-only property that as the string of the human-readable error message which describes the error
  • filename — a read-only string property that has the name of the script of the file in which the error occurred
  • lineno — a read-only integer that has the line number of the script of the file on which the error occurred
  • colno — a read-only integer that has the column number of the script where the error occurred
  • error — a read-only JavaScript object that has the data about the event

If the onerror is a property of anything other than window, then the event handler that we assign to it should have the same signature as we have above, which is only the event parameter which will have the ErrorEvent passed in when an event occurs.

So with the onerror event handler we can handle any error that occurs when loading the page and running the scripts that are loaded on the page. For example, we can use it to handle the situation when an image fails to load by providing an alternative image which we can load.

For example, if we want to load an image that might exist, then we can add an onerror attribute to the img element to load the fallback image like in the following code:

<img src="invalid.gif" onerror="this.src='[https://images.unsplash.com/photo-1556742521-9713bf272865?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1534&q=80'](https://images.unsplash.com/photo-1556742521-9713bf272865?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1534&q=80');" />

To handle errors during script loading, we can write the following code:

<!DOCTYPE html>  
<html>  
  <head>  
    <title>Error</title>  
  </head>  
  <body>  
    <script src="main.js"></script>  
    <script src="error.js"></script>  
  </body>  
</html>

Then in main.js we add our onerror event handler:

window.onerror = (message, source, lineno, colno, error) => {  
  console.log(message);  
  console.log(source);  
  console.log(lineno);  
  console.log(colno);  
  console.log(error.toString());  
};

Then we put some expressions or statements that throws an error in error.js like the following code:

xyz

Then we should get the error logged in our console.log statements inside the onerror event handler in main.js . We should get something like the following output from the console.log statements:

Uncaught ReferenceError: xyz is not defined  
[http://localhost:3000/error.js](http://localhost:3000/error.js)  
1  
1  
ReferenceError: xyz is not defined

The first console.log output has the error message. The second line in the output has the path to the script that caused the error message. Line 3 has the line number of the script where the error occurred. The fourth line has the column number of the line that caused the error, and the last line has the Error object converted to a string, which returns the error message.

If we instead write use the window.addEventListener method to add the event handler, then we can write the following code to log the ErrorEvent object:

window.addEventListener("error", event => {  
  console.log(event);  
});

Then we should get something like the following output from the console.log statement in the event handler above:

bubbles: false  
cancelBubble: false  
cancelable: true  
colno: 1  
composed: false  
currentTarget: Window {parent: Window, postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, …}  
defaultPrevented: false  
error: ReferenceError: xyz is not defined at [http://localhost:3000/error.js:1:1](http://localhost:3000/error.js:1:1)  
eventPhase: 0  
filename: "[http://localhost:3000/error.js](http://localhost:3000/error.js)"  
isTrusted: true  
lineno: 1  
message: "Uncaught ReferenceError: xyz is not defined"  
path: [Window]  
returnValue: true  
srcElement: Window {parent: Window, postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, …}  
target: Window {parent: Window, postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, …}  
timeStamp: 68.510000128299  
type: "error"

In the output above, we get everything from the Event object plus the additional properties from the ErrorEvent object that we listed above like the error property, message property and the filename property.

Conclusion

With the onblur property, we can set an event handler that can handle the blur event. The onerror property lets us set the event handler for when the error event occurs, which happens when something fails to load like an image or a script that fails to run because of some error.

These are handy event handlers that let us handle user interaction and unexpected errors when resource load respectively.

Categories
JavaScript React

Introduction to React Router

React is a library for creating front end views. It has a big ecosystem of libraries that work with it. Also, we can use it to enhance existing apps.

To build single-page apps, we have to have some way to map URLs to the React component to display.

In this article, we’ll look at the basic usage of React Router.

Installation

To use React Router, we have to install it. We can do that by running:

npm i react-router-dom

Basic Usage

React Router has a few basic components.

BrowserRouter

First, there’s the BrowserRouter to do the routing with the HTML5 history API.

It takes a few props:

  • basename — a string prop for the base URL for all locations.
  • getUserConfirmation — a function prop we use to confirm navigation. Defaults to using window.confirm .
  • forceRefresh — a boolean prop that’s true if we want a full refresh on page navigation. It’s useful for imitating traditional server-render apps.
  • keyLength — a number prop that sets the length of location.key . Defaults to 6.
  • children — a React component to render. Before React 16, we can only use a single child element. If we want to render more than one element, we can wrap it in a div.

Switch

Next, there’s the Switch component. It renders the first child Route or Redirect that matches the location.

Switch renders a route exclusively. Route that matches the location renders inclusively.

Switch will only pick one Route to render.

Route

The Route component is the most important component in React Router.

It’s used to map URLs to components and takes the following props:

  • component — we pass in the component to map the URL to by passing in a component to it.
  • render — this prop takes a function that returns something that we want to render.
  • children — a function prop that lets us render something when the path matches Route ‘s path and render something else otherwise.
  • path — a string or array of strings that are paths to match.
  • exact — a boolean prop to that’s true if we want to render only if a path matches exactly.
  • strict — boolean prop that’s true is we only want to match a path with a trailing slash only when the URL entered has a trailing slash. It has no effect when there’re additional URL segments in location.pathname
  • location — an object prop that tries to match its path in the current history location.
  • sensitive — a boolean prop that true if the path is case-sensitive.

Link

The Link component provides accessible navigation around our app.

It takes the following props:

  • to — a string prop with the path that we want to go to. It’s created by concatenating location’s pathname, search and hash properties.
  • to can also be an object that has the pathname, search, state and hash properties. The pathname is a string that has the path to link to. search is a string of the query parameters, hash is a hash top put in the URL, state is the state to persist to the location.
  • to can also be a function which takes the currentlocation as the argument and returns the location representation as a string as an object.
  • replace — a boolean prop that replaces the current entry in the history stack instead of adding one if true
  • innerRef — a function or ref object that we shouldn’t need if we’re using React Router 5.1 or later with React 16. It lets us access the ref of the component.
  • We can any other attribute to the a tag like title , id , className , etc.

Example

We can use the components above together as follows:

import React from "react";  
import ReactDOM from "react-dom";  
import { BrowserRouter as Router, Switch, Route, Link } from "react-router-dom";  
function Home() {  
  return <h2>Home</h2>;  
}

function Foo() {  
  return <h2>Foo</h2>;  
}

function Bar() {  
  return <h2>Bar</h2>;  
}

function App() {  
  return (  
    <Router>  
      <div>  
        <ul>  
          <li>  
            <Link to="/">Home</Link>  
          </li>  
          <li>  
            <Link to="/foo">Foo</Link>  
          </li>  
          <li>  
            <Link to="/bar">Bar</Link>  
          </li>  
        </ul>  
        <Switch>  
          <Route exact path="/">  
            <Home />  
          </Route>  
          <Route path="/foo">  
            <Foo />  
          </Route>  
          <Route path="/bar">  
            <Bar />  
          </Route>  
        </Switch>  
      </div>  
    </Router>  
  );  
}

const rootElement = document.getElementById("root");  
ReactDOM.render(<App />, rootElement);

In the code above, we have the Home , Foo , and Bar components which display some text.

Then we add Router in App and put all our Route s inside so when we click on the Link s, they’ll display the component we specified.

We have:

<Switch>  
    <Route exact path="/">  
        <Home />  
    </Route>  
    <Route path="/foo">  
        <Foo />  
    </Route>  
    <Route path="/bar">  
        <Bar />  
    </Route>  
</Switch>

In the Switch , we have exact in the first Route to only show Home when we go to / .

Then we define 2 more Route s to show Foo when we go to /foo and Bar when we go to /bar .

Conclusion

We can use React Router to map URLs to components. This lets us create a single-page app since we render components according to URLs on the client-side.

Therefore, we’ll have a self-contained app that works on its own without the server rendering things when we type in URLs.

We have the Link to render links, Route to map URLs to components. Router wraps around anything that needs routing.

Switch renders the first child Route or Redirect that matches the location.

Categories
JavaScript React

Intro to React State Management with React-Redux

React is a library for creating front end views. It has a big ecosystem of libraries that work with it. Also, we can use it to enhance existing apps.

To store data in a central place for easy accessibility by components, we have to use some state management solutions. React-Redux is a popular choice.

In this article, we’ll look at how to add it to our React app and simple use cases.

Installation

To install the react-redux package, we have install react-redux and its dependency redux .

We can install both by running:

npm install react-redux redux

with NPM or if we use Yarn:

yarn add react-redux redux

Set Up a Redux Store

After installing both packages, we have to set up our Redux store to hold our data.

To do this we write:

import { createStore } from "redux";

function counterReducer(state = 0, action) {  
  switch (action.type) {  
    case "INCREMENT":  
      return state + 1;  
    default:  
      return state;  
  }  
}

const store = createStore(counterReducer);

The code above creates a Redux store by creating the counterReducer reducer function.

The reducer specifies how the app’s state changes in response to actions sent to the store.

Our counterReducer only accepts one action, which is 'INCREMENT' . We respond to the action by returning the state and adding 1 to it.

There’s also a default case to just return the state value as is.

Then we create a store by calling Redux’s createStore function and passing in our reducer.

It returns the store , which we can pass into our React app.

Connecting the Store to our React App

This is where we need the functions of React-Redux.

We can connect the store to our app so we can store our app’s state in the store by using React-Redux’s connect function.

connect takes 2 functions, which are mapStateToProps and mapDispatchToProps . They’re the first and second argument respectively.

First, we can put the whole app together by connecting our store with the React app as follows:

import React from "react";  
import { Provider, connect } from "react-redux";  
import { createStore } from "redux";  
import ReactDOM from "react-dom";

function counterReducer(state = 0, action) {  
  switch (action.type) {  
    case "INCREMENT":  
      return state + 1;  
    default:  
      return state;  
  }  
}

const store = createStore(counterReducer);

class App extends React.Component {  
  onClick() {  
    this.props.increment();  
  }  
  render() {  
    const { count } = this.props;  
    return (  
      <>  
        <button onClick={this.onClick.bind(this)}>Increment</button>  
        <p>{count}</p>  
      </>  
    );  
  }  
}

const mapDispatchToProps = dispatch => {  
  return {  
    increment: () => dispatch({ type: "INCREMENT" })  
  };  
};  
const mapStateToProps = state => ({  
  count: state  
});App = connect(  
  mapStateToProps,  
  mapDispatchToProps  
)(App);  
const rootElement = document.getElementById("root");  
ReactDOM.render(  
  <Provider store={store}>  
    <App />  
  </Provider>,  
  rootElement  
);

In the code, we have an app that shows a number going up as we click the Increment button.

The first step to connect the store to our React app is to wrap the Provider component around our whole app.

To do this we, wrote the following:

<Provider store={store}>  
  <App />  
</Provider>

Then we define the mapStateToProps and mapDispatchToProps functions as follows:

const mapDispatchToProps = dispatch => {  
  return {  
    increment: () => dispatch({ type: "INCREMENT" })  
  };  
};  
const mapStateToProps = state => ({  
  count: state  
});

In mapStateToProps we return a object to map the state object to a React component prop name as indicated in the property name. The state is the state stored in the Redux store.

So we mapped state to the prop count .

In mapDispatchToProps , we get the dispatch parameter, which is a function used to dispatch our action to the store, and return an object with the name for the function we can access from the props to call and dispatch the action.

So in mapDispatchToProps , increment is our function name. We can call it by running this.props.increment in our App component.

increment is a function that runs dispatch({ type: “INCREMENT” }) .

Then in our App component, we define the onClick method to call this.props.increment to dispatch the ‘INCREMENT’ action to our counterReducer via our Redux store and increase the state by 1.

Then since we have mapStateToProps , the latest value is being observed by App and the latest value is available via this.state.count as indicated in mapStateToProps .

Then when we click the Increment button, we’ll get the number going up by 1.

This will happen with every click.

Conclusion

We can use Redux in our React app by creating a store.

Next, we use the React-Redux Provider component and wrap it around our App entry-point component. We pass our Redux store to the store prop so that we can map the state and dispatch actions to props.

Then connecting it to our store via React Redux’s connect function. We pass in the mapStateToProps and mapDispatchToProps to map the store’s state to our component’s props and map our dispatch function call to our props respectively.

Categories
JavaScript Vue

Add a Tree View to a Vue App with the bootstrap-vue-treeview Library

Creating a tree view from scratch is hard. Therefore, we can make our lives easier with the bootstrap-vue-treeview library.

We can install it by running:

npm install --save bootstrap-vue-treeview

Then we can use it as follows:

main.js

import Vue from 'vue'
import App from './App.vue'
import BootstrapVueTreeview from "bootstrap-vue-treeview";
Vue.use(BootstrapVueTreeview);
Vue.config.productionTip = false

new Vue({
  render: h => h(App),
}).$mount('#app')

App.vue

<template>
  <div id="app">
    <b-tree-view :data="treeData"></b-tree-view>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      treeData: [
        {
          id: 2,
          name: "toyota",
          children: [
            { id: 3, name: "camry" },
            { id: 4, name: "corolla" },
            { id: 5, name: "rav4" },
            { id: 6, name: "prius" }
          ]
        },
        {
          id: 7,
          name: "honda",
          children: [
            { id: 8, name: "accord" },
            { id: 9, name: "civic" },
            { id: 10, name: "cub" }
          ]
        }
      ]
    };
  }
};
</script>

All we had to do is to register the plugin in main.js.

Then we add the b-tree-view component in the template of App.vue and set the data prop to the treeData object, which is returned by the data method.

In addition to the data prop, we can also specify the following props:

Prop Type Description Default value Required
nodeKeyProp String Name of the property containing unique node key "id" No
nodeChildrenProp String Where to look for node children "children" No
nodeLabelProp String Name of the property containing node label "name" No
showIcons Boolean Show/hide icons false No
iconClassProp String Name of the property containing icon class "icon" No
defaultIconClass String Icon class to apply if node has no icon class property null No
prependIconClass String Class to apply to every icon null No
nodesDraggable Boolean Enable or disable drag & drop feature false No
contextMenu Boolean Enable or disable context true No
renameNodeOnDblClick Boolean Enable or disable double click to rename feature true No
contextMenuItems Array of menu items Context menu items [ {code: 'DELETE_NODE', label: 'Delete node' }, { code: 'RENAME_NODE', label: 'Rename node' } ] No

With the code we have. we get:

https://thewebdev.info/wp-content/uploads/2020/04/tree.png

Categories
JavaScript React

Reacting to Observables with MobX-React

We can use MobX with MobX-React to manage the state by watching MobX observables and changing the observable data.

In this article, we’ll look at how to create an Observable and use it in React components directly.

Creating Observables and Using Them in React Components

We have to install the mobx and mobx-react packages to create Observables and use them within React components.

To do this, we can write the following:

npm i mobx mobx-react

Then we can create our Observable object and a React component that uses it as follows:

import React from "react";  
import ReactDOM from "react-dom";  
import { observer } from "mobx-react";  
import { observable } from "mobx";

const countData = observable({  
  count: 0  
});

const App = observer(({ countData }) => (  
  <>  
    <button onClick={() => countData.count++}>Increment</button>  
    <p>{countData.count}</p>  
  </>  
));  
const rootElement = document.getElementById("root");  
ReactDOM.render(<App countData={countData} />, rootElement);

In the code above, we created the countData Observable object by writing:

const countData = observable({  
  count: 0  
});

We’ll be able to get the latest state within our React component and then pass it in as a prop for our React component.

To make our React component watch for the latest value from our Observable object and let us change its value from within the component, we write:

const App = observer(({ countData }) => (  
  <>  
    <button onClick={() => countData.count++}>Increment</button>  
    <p>{countData.count}</p>  
  </>  
));  
const rootElement = document.getElementById("root");  
ReactDOM.render(<App countData={countData} />, rootElement);

The code above gets the countData prop from the countData Observable. Then in the onClick handler, we just pass in the function to change its value.

Then when we reference the App component in the last line, we just pass in the countData Observable object as the value of the countData prop.

countData.count++ will change the state of the Observable, which then the latest value will be obtained from the prop.

We can use the countData Observable object with class components as follows:

import React from "react";  
import ReactDOM from "react-dom";  
import { observer } from "mobx-react";  
import { observable } from "mobx";const countData = observable({  
  count: 0  
});

@observer  
class App extends React.Component {  
  render() {  
    return (  
      <>  
        <button onClick={() => countData.count++}>Increment</button>  
        <p>{countData.count}</p>  
      </>  
    );  
  }  
}

const rootElement = document.getElementById("root");  
ReactDOM.render(<App countData={countData} />, rootElement);

The only difference is that it’s a class component with a render method and that we use the observer decorator instead of the observer function.

Using Context to Pass Observables Around

We can use the React Context API to pass the values of an Observable to another component.

For instance, we can write the following code:

import React, { useContext } from "react";  
import ReactDOM from "react-dom";  
import { observer } from "mobx-react";  
import { observable } from "mobx";

const countData = observable({  
  count: 0  
});

const CountContext = React.createContext();

const Counter = observer(() => {  
  const countData = useContext(CountContext);  
  return (  
    <>  
      <button onClick={() => countData.count++}>Increment</button>  
      <p>{countData.count}</p>  
    </>  
  );  
});

const App = ({ countData }) => (  
  <CountContext.Provider value={countData}>  
    <Counter />  
  </CountContext.Provider>  
);

const rootElement = document.getElementById("root");  
ReactDOM.render(<App countData={countData} />, rootElement);

In the code above, we have the CountContext . We create it by writing:

const CountContext = React.createContext();

Then in App , we included the CountContext component, so that we can get the countData Observable value by passing in the countData prop with the value set to the countData Observable.

In the Counter component, we call the observer function with a function component inside.

Inside the component, we use the useContext hook to get the value from CountContext .

Then in the handler function, we passed into the onClick prop of the button, we changed the count ‘s value, which will automatically change the value in the countData Observable object and set as the value of countData.count .

Therefore, when we click the Increment button, the number below it will go up.

Storing Observables in Local Component State

We can also use Observables as a local state in a React component.

To do this, we can use the useState hook by passing in a function that returns an Observable object as follows:

import React, { useState } from "react";  
import ReactDOM from "react-dom";  
import { observer } from "mobx-react";  
import { observable } from "mobx";const App = observer(() => {  
  const \[countData\] = useState(() =>  
    observable({  
      count: 0  
    })  
  ); return (  
    <>  
      <button onClick={() => countData.count++}>Increment</button>  
      <p>{countData.count}</p>  
    </>  
  );  
});  
const rootElement = document.getElementById("root");  
ReactDOM.render(<App />, rootElement);

In the code above, we used the useState hook by passing in a function that returns an Observable object with the count property. We then assigned that to the countData variable.

Once we did that, countData.count will be updated by the onClick handler and when we click the Increment button, we’ll see the countData.count value update automatically.

If we click the Increment button, then the value will go up.

We don’t really need to use MobX Observable objects to store local state unless complex computations are involved, since MobX will optimize for those.

Likewise, we can use MobX to store local state with class components as follows:

import React, { useState } from "react";  
import ReactDOM from "react-dom";  
import { observer } from "mobx-react";  
import { observable } from "mobx";@observer  
class App extends React.Component {  
  @observable count = 0; render() {  
    return (  
      <>  
        <button onClick={() => this.count++}>Increment</button>  
        <p>{this.count}</p>  
      </>  
    );  
  }  
}  
const rootElement = document.getElementById("root");  
ReactDOM.render(<App />, rootElement);

In the code above, we have this.count , which is an Observable field. In the onClick listener, we just modify this.count directly, and then it’ll be reflected in the this.count in between the p tag.

@observer implements memo orshouldComponentUpdate automatically so that there won’t be any unnecessary re-renders.

Conclusion

We can use MobX Observable to store a React app’s state or a React component’s state.

To use it for storing React app’s state, we can either pass an Observable to a component as a prop or we can use the Context API to send the data to different components.

We can also use it to store local state by either using the useState hook in function components and using the observable decorator within a class component.