a walk through reactjs

September 03, 2020

Reactjs React JS is a open source frontend JavaScript library that focuses on building reach user interfaces. It has a component based architecture and handles DOM update gracefully. You can integrate other third party packages into react and react too integrate with other applications or a portion of an application gracefully.

To get started with reactjs you need nodejs, a code editor and npm.

install create-react-app with npm

npm install create-react-app -g

Create your reactjs project with npx and open it in your code editor.

npx create-react-app project-name

move into your project folder and run npm start to start a local live server on port 3000.

Components are part of the UI. There are two types of components:

  • Functional components
  • Class components

Reactjs uses jsx(JavaScript XMl) an extension of JavaScript language syntax which allows you to write xml like code which is intuitive and easy to understand. It translates to regular JavaScript.

React with jsx.

import React from 'react'

export default function Hello() {
    return (
        <div id="hello">
            <h1 className="text">Hello World</h1>
        </div>
    )
}

React without jsx.

import React from 'react'

export default function Hello() {
    return React.createElement("div", {id:"hello"}, React.createElement("div", {className:"text"}, "Hello World"))
}

Props

Props are immutable. Working with props in react.Here we create props in the hello.js and pass them in the app.js

hello.js

import React from 'react'

////With functional component
// function Hello(props) {
//     console.log(props)
//     return (
//         <div>
//            <h1> Hello {props.name}</h1> 
//            <h1>Hero {props.hero}</h1>
//            {props.children}
//         </div>
//     )
// }

////With class component
class Hello extends React.Component {
    render() {
        return(
            <div>
                <h1>Hello {this.props.name}</h1>
                <h1>Hero {this.props.hero}</h1>
                {this.props.children}
            </div>
        )
    }
}

export default Hello

app.js

import React from "react";
import Hello from './components/hello';

function App() {
  return (
    <div className="App">
      <Hello name="Davis" hero="Flash">
        <p>Likes JavScript</p>
        </Hello>
      <Hello name="ken" hero="Batman"/>
      <Hello name="Marion" hero="Wonder woman"/>
    </div>
  );
}

export default App;

props.children allows you to pass individual props to individual components.

Destructuring props

With function parameters.

function Hello({name, hero}) {
    return (
        <div>
           <h1> Hello {name}</h1> 
           <h1>Hero {hero}</h1>
        </div>
    )
}
export default Hello

In the component body.

function Hello(props) {
    const {name, hero} = props;
    return (
        <div>
           <h1> Hello {name}</h1> 
           <h1>Hero {hero}</h1>
        </div>
    )
}
export default Hello

In class components

class Hello extends React.Component {
    render() {
        const {name, hero} = this.props;
        return(
            <div>
                <h1>Hello {name}</h1>
                <h1>Hero {hero}</h1>
            </div>
        )
    }
}

export default Hello

passing methods as props

parent.js

import React from 'react';
import Hello from './hello';
class Parent extends React.Component {
    constructor(){
        super();
        this.state = {
            parentName: "parent"
        }
       
    }

    greetParent = () => {
        console.log(`hello ${this.state.parentName}`)
    }

    render() {
        return(
            <div>
                <Hello greetHandler ={this.greetParent} />
                
            </div>
        )
    }
}


export default Parent

child.js

import React from 'react'

function Hello(props) {
    return (
        <div>
            <button onClick={() => props.greetHandler(`child`)}>Greet Parent</button>
        </div>
    )
}

export default Hello;

With parameters

parent.js

import React from 'react';
import Hello from './hello';
class Parent extends React.Component {
    constructor(){
        super();
        this.state = {
            parentName: "parent"
        }
       
    }

    greetParent = (childName) => {
        console.log(`hello ${this.state.parentName} from ${childName}`);
    }

    render() {
        return(
            <div>
                <Hello greetHandler ={this.greetParent} />
                
            </div>
        )
    }
}


export default Parent

State

state should not be updated directly instead use useState.

import React from 'react';

class Hello extends React.Component {
    constructor(){
        super();
        this.state = {
            count: 0,
            count2: 0
        }
        this.increment = this.increment.bind(this);
    }
    //use callback function
    increment() {
        this.setState({count: this.state.count + 1}, ()=>{
            console.log(this.state.count);
        })

        //using previous state
        this.setState((prevState, props) => ({
            count2: prevState.count2 + 1
            // count2: prevState.count2 + props.value
        }))
    }
    render() {
        return(
            <div>
                <h1>Count {this.state.count}</h1>
                <h1>Count2 {this.state.count2}</h1>
                <button onClick={this.increment}>Increment</button>
            </div>
        )
    }
}

export default Hello

Event handling

import React from 'react';

class Hello extends React.Component {
    constructor(){
        super();

    }
    handleClick = () => {
        console.log("hello")
    }

    render() {
        return(
            <div>

                <button onClick={this.handleClick}>Click</button>
    
            </div>
        )
    }
}


export default Hello

Binding event handlers

Event handlers are bind because of this keyword

import React from 'react';

class Hello extends React.Component {
    constructor(){
        super();
        this.state = {
            greeting: "hi"
        }
        this.clickHandler = this.clickHandler.bind(this);
    }
    clickHandler(){
        this.setState({greeting: "hello"})
    }
    //doesn't require binding
    handleClick = () => {
        this.setState({greeting: "hello"})
    }

    render() {
        return(
            <div>

                <h1>{this.state.greeting}</h1>
                <button onClick={this.handleClick}>Click</button>
                <button onClick={this.handleClick.bind(this)}>Click2</button>
                <button onClick={()=>{
                    this.handleClick();
                }}>Click3</button>
            </div>
        )
    }
}


export default Hello

Conditional Rendering

If … else

import React from 'react';

class Hello extends React.Component {
    constructor(){
        super();
        this.state = {
            isLoggedIn:false
        }
    }

    render() {
        if(this.state.isLoggedIn) {
            return(
                <div>
                     <h1>Welcome Davis</h1>
                </div>
            )
        } else{
        return(
            <div>
                <h1>Welcome  Guest</h1>
            </div>
        )
    }
    }
}


export default Hello;

Element variables

import React from 'react';

class Hello extends React.Component {
    constructor(){
        super();
        this.state = {
            isLoggedIn:false
        }
    }

    render() {
        let message;
        if(this.state.isLoggedIn) {
                message =  <h1>Welcome Davis</h1>;
        } else{
                message = <h1>Welcome  Guest</h1>;
    }

    return <div>{message}</div>
    }
}

export default Hello;

Ternary operators

import React from 'react';

class Hello extends React.Component {
    constructor(){
        super();
        this.state = {
            isLoggedIn:false
        }
    }

    render() {
    return (
    <div>
        {this.state.isLoggedIn ? <h1>Welcome Davis</h1> : <h1>Welcome  Guest</h1>}

        or render blank if false

        {this.state.isLoggedIn && <h1>Welcome Davis</h1>}
    </div>
    )
    }
}

export default Hello;

List rendering

import React from 'react';

function Hello() {

    const colors = ["pink", "blue", "white"];
    const colorList = colors.map(color=> <h2>{color}</h2>)
    return (
    <div>
        {colors.map(color => 
            <h1>{color}</h1>
        )}

        {colorList}
    </div>
    )
    }

export default Hello;

Lists and keys.Keys are not accessible in the child component.

import React from 'react';

function Hello() {

    const colors = ["pink", "blue", "white"];
    const colorList = colors.map(color=> <h2 key= {color}>{color}</h2>)
    return (
    <div>
        {colors.map(color => 
            <h1 key={color}>{color}</h1>
        )}

        {colorList}
    </div>
    )
    }

export default Hello;

Using index as key. It’s not recommended especially when the items can be removed or others added at the beginning. Use index as a key when:

  • your items don’t have an id
  • your list is static and won’t change
  • your list won’t be reordered or filtered.
import React from 'react';

function Hello() {

    const colors = ["pink", "blue", "white"];
    const colorList = colors.map((color, index)=> <h2 key= {index}>{color}</h2>)
    return (
    <div>
        {colors.map((color,index) => 
            <h1 key={index}>{index} - {color}</h1>
        )}

        {colorList}
    </div>
    )
    }

export default Hello;

Styling

CSS Stylesheets

import './index.css';

Inline Styling

import React from 'react';

const styles = {
    color: 'blue',
    fontSize: '60'
}
function Hello() {
    return (
    <div>
        <h1 style= {styles}>Hello</h1>
    </div>
    )
    }

export default Hello;

Forms

import React, { Component } from 'react'

export class hello extends Component {
    constructor(props) {
        super(props);

        this.state = {
            name: "",
            description: "",
            color: ""
        }
    }

    handleName = (event) => {
        event.preventDefault();

        this.setState({name: event.target.value})
    }

    handleDesc = (event) => {
        event.preventDefault();

        this.setState({description: event.target.value})
    }

    handleColor = (event) => {
        event.preventDefault();

        this.setState({color: event.target.value})
    }
    render() {
        return (
            <div>
                <label htmlFor="name">Name</label>
                <input type="text" value={this.state.name} onChange = {this.handleName}/>

                <label htmlFor="description">Description</label>
                <textarea name="description" id="desc" cols="30" rows="10" value = {this.state.description} onChange = {this.handleDesc}></textarea>

                <label htmlFor="color">color</label>
                <select name="color" id="clr" onChange= {
                    this.handleColor
                }>
                    <option value="blue">blue</option>
                    <option value="green">green</option>
                    <option value="red">red</option>
                </select>
            </div>
        )
    }
}

export default hello

Lifecycle Methods

Mounting phase

Components are mounted after all the children have been rendered.

import React, { Component } from 'react'

export class Hello extends Component {
    constructor(props) {
        super(props);

        this.state = {
            name: "Davis"
        }
        console.log("Lifecycle1 - constructor")
    }

    static getDerivedStateFromProps(props,state) {
        console.log("Lifecycle1 - getDerivedStateFromProps")
    }

    componentDidMount() {
        console.log("Lifecycle1 - componentDidMount")
    }

    render() {
        console.log("Lifecycle1 - render")
        return (
            <div>
                <h1>hey</h1>
            </div>
        )
    }
}

export default Hello

UPdating phase

import React, { Component } from 'react'

export class Hello extends Component {
    constructor(props) {
        super(props);

        this.state = {
            name: "Davis"
        }
        console.log("Lifecycle1 - constructor")
    }

    static getDerivedStateFromProps(props,state) {
        console.log("Lifecycle1 - getDerivedStateFromProps")
        return null;
    }

    componentDidMount() {
        console.log("Lifecycle1 - componentDidMount")
    }

    shouldComponentUpdate() {
        console.log("Lifecycle1 - shouldComponentUpdate")
        return true;
    }

    getSnapshotBeforeUpdate(prevProps, prevState) {
        console.log("Lifecycle1 - getSnapshotBeforeUpdate")
        return null;
    }

    componentDidUpdate() {
        console.log("Lifecycle1 - componentDidUpdate")
    }

    changeName = (e) =>{
        e.preventDefault();

        this.setState({name: "Bwake"})
    }

    render() {
        console.log("Lifecycle1 - render")
        return (
            <div>
                <h1>hey</h1>
                <button onClick= {this.changeName}>button</button>
            </div>
        )
    }
}

export default Hello

PureComponent

import React, { PureComponent } from 'react'

export default class Hello extends PureComponent {
    constructor(props) {
        super(props);

        this.state = {
            name: "Davis"
        }
    }

    componentDidMount() {
        setInterval(() => {
            this.setState({
                name: "Davis"
            })
        }, 2000)
    }
    render() {
        console.log("pure component");
        return (
            <div>
                <h1>Pure component {this.state.name}</h1>
            </div>
        )
    }
}

memo

import React from 'react'

function Hello({name}) {
    console.log('Render memo')
    return (
        <div>
            {name}
        </div>
    )
}

export default React.memo(Hello);

refs

import React, { Component } from 'react'
import PropTypes from 'prop-types'

export class Hello extends Component {
    constructor(props) {
        super(props);

        this.inputRef = React.createRef();
        this.cbRef = null;
        this.setCbRef = (element) => {
            this.cbRef = element
        }
    }

    componentDidMount(){
        this.inputRef.current.focus();
        console.log(this.inputRef)

        if(this.cbRef) {
            this.cbRef.focus()
        }
    }

    btnHandler = () => {
        console.log(this.inputRef.current.value)
    }
    render() {
        return (
            <div>
                <input type="text" ref={this.inputRef}/>
                <input type="text" ref={this.setCbRef}/>

                <button onClick={this.btnHandler}>button</button>
            </div>
        )
    }
}

export default Hello

Portals

Gives you the ability to breakout of DOM element

index.html

    <div id="root"></div>
    <div class="portal-root"></div>

component.js

import React from 'react';
import ReactDOM from 'react-dom';

function PortalComp() {
    return ReactDOM.createPortal(
            <h1>Portal demo</h1>,
            document.getElementById('portal-root')
    )
}

export default PortalComp;

Error handling

Error boundaries are REact components that catch javaScript error in their child component tree, log this errors and display a fall-back UI.

A class component becomes an Error Boundary by defining either or both of getDErivedFromError and componentDidCatch lifecycle methods.

The placement of the Error Boundary matters as it controls if the entire app should have the fall-back UI or just a component causing the problem. It provides a way to gracefully handle error in application code.

import React, { Component } from 'react'

export class ErrorBoundary extends Component {

    constructor(props) {
        super(props);

        this.state = {
            hasError: false
        }
    }
    static getDerivedStateFromError(error) {
        return {
            hasError: true
        }
    }
        componentDidCatch(error, info) {
        return{
            hasError:true
        }
    }
    render() {
        if(this.state.hasError) {
            return <h1>Something went wrong</h1>
        }
        return this.props.children
    }
}

export default ErrorBoundary

Higher order components - HOC

Helps share common functionality between components

import React from 'react'

const UpdatedComponent = OriginalComponent => {
    class NewComponent extends React.Component {
        constructor(props) {
            super(props);
    
            this.state = {
                count: 0
            }
        }
    
        incrementCount = () => {
            this.setState(prevState => {
                return {count: prevState.count + 1 }
            })
        }
        render() {
            return <OriginalComponent count={this.state.count}
            incrementCount={this.incrementCount} />
        }
    }
    return NewComponent
}

export default UpdatedComponent
import React, { Component } from 'react'
import UpdatedComponent from './withCounter';

export class HoverCounter extends Component {
 
    render() {
        const {count, incrementCount} = this.props;
        return (
            <div>
                <h2 onMouseOver = {incrementCount}>  Hovered {count} timer</h2>
            </div>
        )
    }
}

export default UpdatedComponent(HoverCounter) 

Profile picture

Written by Davis Bwake A fullstack developer who likes JavaScript and everything web 3.0(BlockChain..) follow me on twitter

My tech stack is HTML, CSS,JavaScript, ReactJS, NodeJS, Solidity

Am currently open to remote job oppurtunities.

Checkout my projects

YouTube