Module: Components and Props

Functional Components

Functional Components in React

Functional components are a simpler way to define React components. They are essentially JavaScript functions that accept props as arguments and return React elements describing what should be rendered to the DOM.

Key Characteristics:

  • JavaScript Functions: They are plain JavaScript functions, not classes.
  • Props as Arguments: They receive data through arguments called props.
  • Implicit Return: Often use implicit returns with arrow functions for concise syntax.
  • No this Keyword: Don't have access to the this keyword.
  • Hooks (introduced in React 16.8): Can use React Hooks to manage state and lifecycle features, making them powerful enough to handle complex logic.

Example:

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

// Or using an arrow function:
const WelcomeArrow = (props) => {
  return <h1>Hello, {props.name}</h1>;
}

Explanation:

  • Welcome and WelcomeArrow are functional components.
  • They both accept a single argument, props, which is an object containing the properties passed to the component.
  • Inside the function, we access the name property from the props object using props.name.
  • The function returns a JSX expression that defines the HTML to be rendered.

Rendering a Functional Component:

Just like class components, you render functional components using JSX:

ReactDOM.render(
  <Welcome name="Sara" />,
  document.getElementById('root')
);

ReactDOM.render(
  <WelcomeArrow name="John" />,
  document.getElementById('root')
);

Props:

Props (short for properties) are how you pass data from a parent component to a child component. They are read-only from the child component's perspective.

  • Passing Props: Props are passed as attributes to the component when it's rendered. For example: <Welcome name="Sara" /> passes a prop named name with the value "Sara".
  • Accessing Props: Props are accessed as properties of the props object within the functional component. For example: props.name.
  • Prop Validation (PropTypes): You can use PropTypes to define the expected types of props, helping to catch errors during development. (See section below)

Example with Multiple Props:

function Greeting(props) {
  return (
    <p>
      Hello, {props.firstName} {props.lastName}! You are {props.age} years old.
    </p>
  );
}

ReactDOM.render(
  <Greeting firstName="Jane" lastName="Doe" age={30} />,
  document.getElementById('root')
);

Default Props:

You can provide default values for props if they are not explicitly passed by the parent component.

function Profile(props) {
  return (
    <div>
      Name: {props.name} <br />
      Bio: {props.bio}
    </div>
  );
}

Profile.defaultProps = {
  name: 'Guest',
  bio: 'No bio provided.'
};

ReactDOM.render(
  <Profile />, // Uses default props
  document.getElementById('root')
);

ReactDOM.render(
  <Profile name="Alice" bio="Software Engineer" />, // Overrides default props
  document.getElementById('root')
);

PropTypes (for Prop Validation):

PropTypes is a library (often used with React) that allows you to specify the expected data types for props. This helps catch errors early in development.

import PropTypes from 'prop-types';

function Button(props) {
  return <button>{props.label}</button>;
}

Button.propTypes = {
  label: PropTypes.string.isRequired // 'label' must be a string and is required
};

// Example of incorrect usage:
// ReactDOM.render(<Button label={123} />, document.getElementById('root')); // Will show a warning in the console

Benefits of Functional Components:

  • Simpler and More Concise: Easier to read and understand than class components, especially for simple UI elements.
  • Improved Performance (potentially): Can sometimes lead to performance improvements because they avoid the overhead of creating class instances. (However, the difference is often negligible).
  • Hooks Enable State and Lifecycle Features: Hooks allow functional components to manage state and perform side effects, making them just as powerful as class components.
  • Easier to Test: Functional components are easier to test because they are just functions.

When to Use Functional Components:

  • For most components, especially those that primarily focus on rendering UI based on props.
  • When you don't need complex state management or lifecycle methods (or when you can handle them with Hooks).
  • When you want a more concise and readable component definition.

In modern React development, functional components with Hooks are the preferred way to build components. They offer a more streamlined and efficient approach to component creation.