useEffect Hook in React

The useEffect Hook in React is a function that lets you perform side effects in functional components. A side effect is anything that affects something outside the scope of the function being executed, such as data fetching, subscriptions, or manually changing the DOM. Essentially, it’s a way to tell React that your component needs to do something after rendering.

The useEffect Hook is a great tool for managing the lifecycle of your components, allowing you to perform actions at specific points in time, like when the component first mounts, when it updates, or when it unmounts.

How It Works

useEffect(setup, dependencies)

1. Running an Effect on Every Render

import React, { useState, useEffect } from 'react';

function MyComponent() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    // This effect runs on every render
    console.log(`The count is: ${count}`);
  });

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

2. Running an Effect Only Once (on Mount)

import React, { useState, useEffect } from 'react';

function DataFetcher() {
  const [data, setData] = useState(null);

  useEffect(() => {
    // This effect runs only once, when the component mounts
    fetch('https://api.example.com/data')
      .then(response => response.json())
      .then(json => setData(json));
  }, []); // The empty array ensures this effect runs only once

  return (
    <div>
      {data ? <pre>{JSON.stringify(data, null, 2)}</pre> : <p>Loading...</p>}
    </div>
  );
}

3. Running an Effect When Dependencies Change

import React, { useState, useEffect } from 'react';

function UserProfile({ userId }) {
  const [user, setUser] = useState(null);

  useEffect(() => {
    // This effect runs whenever 'userId' changes
    console.log('Fetching user data...');
    fetch(`https://api.example.com/users/${userId}`)
      .then(response => response.json())
      .then(json => setUser(json));
  }, [userId]); // The effect re-runs when userId changes

  return (
    <div>
      {user ? <h1>User: {user.name}</h1> : <p>Select a user</p>}
    </div>
  );
}

4. Cleanup Function

import React, { useState, useEffect } from 'react';

function Timer() {
  const [seconds, setSeconds] = useState(0);

  useEffect(() => {
    const intervalId = setInterval(() => {
      setSeconds(prevSeconds => prevSeconds + 1);
    }, 1000);

    // This is the cleanup function
    return () => {
      clearInterval(intervalId);
      console.log('Timer cleaned up!');
    };
  }, []); // Empty dependency array means this effect runs once on mount

  return <h1>Seconds: {seconds}</h1>;
}

 

useState Hook in React

The useState hook allows a function component to have state. It returns a pair: the current state value and a function to update it.

import './App.css'
import {useState} from "react";

function App() {

    // Simple numeric state for Counter 1
    const [count, setCount] = useState(4);
    // Object state for Counter 2 (represents a person with name and age)
    const [person, setPerson] = useState({name: "John", age: 30});

    // Decrement the numeric counter. Using the functional form of setState
    // ensures we always operate on the latest state value.
    function decrementCounter() {
        setCount(prevState => prevState - 1);
    }

    // Increment the numeric counter (Counter 1)
    function incrementCount() {
        setCount(prevState => prevState + 1);
    }

    // Decrement the person's age. Use the spread operator to preserve other
    // properties on the person object when updating nested state.
    function decrementCounter2() {
        setPerson(prevState => {
            return {...prevState, age: prevState.age - 1}
        });
    }

    // Increment the person's age (Counter 2)
    function incrementCount2() {
        setPerson(prevState => {
            return {...prevState, age: prevState.age + 1}
        });
    }

    return (
        <>
            {/* Counter 1: shows a simple number and two buttons to change it */}
            <div>
                <span>Counter 1: </span><span>{count}</span>
                <button onClick={decrementCounter}>-</button>
                <button onClick={incrementCount}>+</button>
            </div>

            {/* Counter 2: displays person object fields and buttons to update age.
                Note: name is not changed here; only age is updated via setPerson. */}
            <div>
                <span>Counter 2: </span>
                <span>Name: {person.name}, Age:{person.age}</span>
                <button onClick={decrementCounter2}>+</button>
                <button onClick={incrementCount2}>+</button>
            </div>
        </>
    )
}

export default App

Using a function as the initial state parameter is a performance optimization. It’s recommended when the initial state is the result of a computationally expensive or complex calculation.

Without a function, the expensive calculation would run on every render of the component, even if the state isn’t being re-initialized. By wrapping the calculation in a function and passing that function to useState, the calculation will only run once on the first render. This prevents unnecessary work and improves performance.

// Example with a direct value (inefficient for heavy computation)
function MyComponent() {
  // This function runs on every single render
  const initialValue = someExpensiveCalculation();
  const [data, setData] = useState(initialValue);
  // ...
}

// Example with a function (lazy initializer)
function MyComponentLazy() {
  // The function passed to useState is a lazy initializer.
  // React will only call it once on the initial render.
  const [data, setData] = useState(() => {
    return someExpensiveCalculation();
  });
  // ...
}

References
https://react.dev/reference/react/useState

Set Battery Charge Limit in EndeavourOS

sudo nano /etc/systemd/system/battery-charge-limit.service
[Unit]
Description=Set the battery charge limit to 80%
After=multi-user.target

[Service]
Type=oneshot
ExecStart=/bin/bash -c 'echo 60 > /sys/class/power_supply/BAT0/charge_control_end_threshold'

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable battery-charge-limit.service
sudo systemctl start battery-charge-limit.service

 

Set Permanently ulimit -n / open files in Arch

sudo nano /etc/sysctl.conf
fs.file-max = 65535
fs.inotify.max_user_watches = 524288
sudo sysctl -p
sudo nano /etc/security/limits.conf
# add following lines to it
* soft     nproc          65535    
* hard     nproc          65535   
* soft     nofile         65535   
* hard     nofile         65535
root soft     nproc          65535    
root hard     nproc          65535   
root soft     nofile         65535   
root hard     nofile         65535
sudo nano /etc/pam.d/common-session
# add this line to it
session required pam_limits.so

 

Installing a package in Go

To install a package, open your terminal or command prompt and run the following command:

go get [package path]

For example, to install the popular Chi router package, you would type:

go get github.com/go-chi/chi/v5

After you run this command, Go automatically downloads the package and its dependencies and adds them to your go.mod file, which tracks your project’s dependencies.

Dependency Management

Since Go version 1.11, the official way to manage dependencies is with Go Modules. When you install a package with go get, Go automatically updates your project’s go.mod and go.sum files.

  • go.mod: Lists your project’s direct and indirect dependencies with their specific versions.
  • go.sum: Contains cryptographic checksums of the module dependencies to ensure their integrity.

If you are inside a Go module (a directory with a go.mod file), go get updates that module. If you are not in a module, go get simply installs the package into a global cache. However, it’s best practice to always work within a Go module. You can initialize a new module with go mod init [module path].

Using the LTS kernel in EndeavourOS

sudo pacman -Syu linux-lts linux-lts-headers

Kernel Management Tool (AKM): EndeavourOS also has a kernel management tool called akm (Arch Kernel Manager) in its repositories. You can install it with sudo pacman -S akm and use it as a graphical interface to easily install and manage different kernels.