Skip to main content

React JS Basics

 What are side effects in React?

In React, side effects are operations that interact with external systems or cause changes outside the component's rendering process. These can include:

  • Data fetching: Retrieving data from APIs or other sources.
  • Subscriptions: Setting up listeners for events or data changes.
  • Timers: Creating timers for delayed actions or animations.
  • DOM manipulation: Directly modifying the DOM (rarely used in modern React with declarative approach).

Why use useEffect?

In class-based components, you would typically use lifecycle methods like componentDidMount, componentDidUpdate, and componentWillUnmount to handle side effects. Functional components don't have these methods directly.

The useEffect Hook provides a way to manage side effects in functional components. It allows you to run a function after a component renders (or re-renders) and optionally clean up any resources created by that function before the component unmounts.

How does useEffect work?

useEffect takes two arguments:

  1. Effect function: This function contains the side effect logic, such as fetching data or setting up a timer.
  2. Dependency array (optional): This is an array of values that control when the effect function runs. If the dependency array is omitted, the effect function runs after every render. If the dependency array includes values, the effect function only runs when one or more of those values change.

what are different types of hooks in react ?

React hooks can be broadly categorized into a few main types based on their functionality:

1. State Hooks:

  • useState: The most fundamental hook, allowing you to create state variables within functional components. It returns an array with the current state value and a function to update it.

2. Effect Hooks:

  • useEffect: The workhorse for side effects in functional components. It lets you perform actions like data fetching, subscriptions, or DOM manipulations after the component renders or re-renders. You can optionally control when it runs using a dependency array.

3. Context Hooks:

  • useContext: Provides a way to share data across components without explicit prop drilling. It allows components to access context values defined higher up in the component tree.

4. Ref Hooks:

  • useRef: Creates a mutable ref object that persists throughout the component's lifecycle. It's useful for storing DOM node references, managing focus, or integrating with third-party libraries.

5. Callback Hooks (less common):

  • useCallback: Memoizes a callback function, preventing unnecessary re-renders of child components that rely on it if its dependencies haven't changed.
  • useMemo: Memoizes the result of an expensive function call, avoiding re-calculations if the dependencies haven't changed.

Additional Hooks:

  • useReducer: An alternative state management approach for complex components, similar to useState but using a reducer function to update state.
  • useLayoutEffect: Similar to useEffect but runs synchronously after DOM mutations, useful for specific layout-related effects.
  • useDebugValue: A development-only hook to display custom values in React DevTools for debugging purposes.

Understanding these different types of hooks and their use cases is essential for building well-structured and efficient React applications.


React Lifecycle Methods

In React, components have a well-defined lifecycle that they go through from creation to destruction. This lifecycle is managed by a set of built-in methods that you can implement in your class-based components to perform specific actions at different stages. These methods are called lifecycle methods.

The Three Main Phases:

The React component lifecycle can be broken down into three main phases:

  1. Mounting: This phase begins when a component is first created and inserted into the DOM. Here are the methods associated with this phase:

    • constructor: This is an optional method where you can initialize state using this.state = {}. It's generally not used for side effects like data fetching.
    • getDerivedStateFromProps (optional): This method is invoked right before rendering the component, allowing you to derive state based on changes in props. It's useful for setting up state based on incoming data.
    • render: This is a required method that defines what the component will render in the DOM. It should be a pure function, returning JSX elements that represent the component's UI.
    • componentDidMount: This method is called after the component has been rendered in the DOM. It's a good place to perform side effects like data fetching, subscriptions, or DOM manipulation that requires the component to be fully in the DOM.
  2. Updating: This phase occurs when a component's state or props change, causing a re-render. The following methods are involved:

    • getDerivedStateFromProps (optional): Can be used again here to update state based on new props.
    • shouldComponentUpdate (optional): This method allows you to control whether the component should re-render based on state or props changes. It's an optimization technique, but use it cautiously.
    • render: Called again to re-render the component with the updated state or props.
    • getSnapshotBeforeUpdate (rarely used): This method is invoked right before the browser updates the DOM, allowing you to capture a snapshot of the DOM (e.g., scroll position) for later use.
    • componentDidUpdate: This method is called after the component has been updated in the DOM. It's a good place to perform side effects that depend on the component's state or props having been updated.
  3. Unmounting: This phase happens when a component is removed from the DOM. The following method is associated with it:

    • componentWillUnmount: This method is called just before the component is removed from the DOM. It's a good place to clean up any subscriptions, timers, or other resources that the component created.

Key Considerations:

  • These methods are called in the order listed within each phase.
  • Lifecycle methods are primarily used in class-based components. Functional components can leverage hooks like useEffect for side effects management.
  • While lifecycle methods provide a structured way to handle component behavior at different stages, use them judiciously. Overly complex logic within lifecycle methods can make components harder to maintain. Consider other techniques like state management solutions or refactoring for better organization.

By understanding these lifecycle methods, you can create more robust and well-behaved React components.


Here's an example of how to use useContext in React to share data across components without prop drilling:

1. Create the Context:

First, we'll create a context using React.createContext(). This context will hold the data you want to share between components.

JavaScript
import React, { createContext, useState } from 'react';

const ThemeContext = createContext({ theme: 'light' });

export default ThemeContext;

2. Provide the Context Value:

Next, we need to wrap the part of your component tree where you want to make the context value available with a context provider component. This component will be responsible for providing the actual value to the context.

JavaScript
function App() {
  const [theme, setTheme] = useState('light');

  const toggleTheme = () => {
    setTheme(theme === 'light' ? 'dark' : 'light');
  };

  return (
    <ThemeContext.Provider value={{ theme, toggleTheme }}>
      <Content />
    </ThemeContext.Provider>
  );
}

In the App component, we're using the ThemeContext.Provider component to provide the current theme state and a function to toggle the theme (toggleTheme). This provider component wraps the Content component (which we'll create next).

3. Consume the Context in Child Components:

Now, in any child component that needs access to the context value, you can use the useContext hook to retrieve it.

JavaScript
import React, { useContext } from 'react';

const ThemeContext = React.createContext({ theme: 'light' });

function Content() {
  const { theme, toggleTheme } = useContext(ThemeContext);

  return (
    <div>
      <p>Current theme: {theme}</p>
      <button onClick={toggleTheme}>Toggle Theme</button>
      <Settings />
    </div>
  );
}

export default Content;

Here, the Content component imports the ThemeContext and uses useContext to access the current theme and the toggleTheme function provided by the context provider in the App component. You can then use this data and function within your component's logic and rendering.

4. Optional: Nested Contexts:

While useContext is powerful, use it sparingly for deeply nested components. Consider alternative approaches like state management solutions (Redux, MobX) for complex data sharing scenarios.

Explanation:

In this example, the ThemeContext provides a way to share the theme state and toggle function across the Content component and potentially its nested child components (like Settings in this example) without having to pass them down as props through every level. This keeps your components cleaner and avoids prop drilling.

Remember, this is a basic example. You can use useContext to share any kind of data you need across different parts of your component tree.


If you don't use Redux for state management in a ReactJS application

Challenges with Local State Management:

  • Prop Drilling: As your application grows and components need to share state across many levels, you might resort to passing data down through props. This can lead to "prop drilling," where props become deeply nested and harder to manage.
  • State Consistency: Maintaining consistency across multiple components that rely on the same data becomes difficult. Updates in one component might not be reflected in others that need the same information.
  • Debugging Complexity: Tracking down the source of state-related issues becomes more challenging without a centralized view of the application's state.

Potential Issues:

  • Increased Code Complexity: Complex logic for managing state updates and keeping components in sync can make the codebase harder to understand and maintain.
  • Unintended Side Effects: State changes in one component might unintentionally affect another due to a lack of clear communication between components.
  • Performance Issues: Unnecessary re-renders can occur if components are not optimized to update only when the relevant part of the state changes.

Alternatives to Redux:

  • React Context API: A built-in React feature for sharing data across components without prop drilling. It's simpler than Redux for smaller applications or isolated state needs.
  • useState Hook: For managing local component state, it's the most straightforward approach for simple applications.

Choosing the Right Tool:

  • Redux is ideal for complex applications with a lot of shared state and a need for predictability and maintainability.
  • For smaller applications or those with more isolated state needs, React's built-in state management tools (useState and Context API) might be sufficient.

Comments

Popular posts from this blog

Safety property that a deadlock can never occur

Identified four necessary conditions for a deadlock to occur 1. Mutual Exclusion. The nodes claim exclusive control of the resources they require. 2. Wait for. Tasks hold resources already allocated to them while waiting for additional resources. 3. No preemption. Resources cannot be forcibly removed from the tasks holding them until the resources are used to completion. 4. Cyclic Wait. A cyclic chain of tasks exists, such that each task holds one or more resources that are being requested by the next task in the chain. References: For information about system deadlocks please refer: E. G. Coffman, M. Elphick, and A. Shoshani. System Deadlocks

OWASP API Security Top 10 vulnerabilities 2023

API Security Do's and Don'ts Don't trust input data for an API and do validate all inputs. Ensure you understand security and keep sensitive data out of code. Don't hardcode keys/tokens Don't reveal useful info in error messages. Don't have hidden/unadvertised features. Don't filter data in UI - control at app level Don't confuse authentication and authorization Always use API gateways to control access and traffic Do require API documentation. Do expect users/hackers to find and use undocumented endpoints Do continuous testing - attack simulation, test configs, fuzzing, injections OWASP API Security Top 10 Vulnerabilities 2023 API-1:2023 - Broken Object Level Authorization: BOLA is still the leading vulnerability that plagues APIs. When data objects do not have sufficient access controls in place, resources can be accessed by unauthorized users. API-2:2023 - Broken Authentication  Broken Authentication contains all vulnerabilities associated with auth...
Program to print items in single linkedlist in Pendulum order  Single linked list pendulum in java There are sequence of numbers in a single linked list and display the result in pendulum format Input : 1 2 3 4 5 6 7 8 Output : 1 8 2 7 3 6 5 4 Solution :  https://github.com/Bonu/datastructures/blob/main/SingleLinkedListPendulum.java Below is the manual approach: Input: 1 2 3 4 5 6 7 Iteration 1: 1 2 3 4 5 6 7 Iteration 2: 1 7 2 3 4 5 6 Iteration 3: 1 7 2 6 3 4 5 Iteration 4: 1 7 2 6 3 5 4