React Redux TypeScript

 

Advanced React

Instructor

Marcin Kieruzel

I'm a Software Engineer.

I run a small software house –

No Input Signal 

 

We do front-end and back-end development and graphic design. We specialize in React, React Native, Node.js and some PHP and Python as well.

Schedule


Start time: 11.00

End time: 16.00

 

Higher-order components
Using Advanced Hooks

React and TypeScript

Redux

Authentication

Testing and Debugging

Optimizing performance

Deployment

Troubleshooting

Summary and Conclusion

HOC

Higher-Order Components (HOCs) are a pattern in React, derived from higher-order functions in JavaScript. In React, a HOC is a function that takes a component and returns a new component, allowing you to reuse component logic.

HOC

Understanding HOCs

A HOC can be used for many purposes, such as:

  • Code reuse, logic and bootstrap abstraction
  • Render hijacking
  • State abstraction and manipulation
  • Props manipulation

HOC

Basic Structure of a HOC

A simple HOC might look something like this when applied to functional components:

// HOC definition
function withSampleHOC(WrappedComponent) {
  return function(props) {
    // Add or modify logic here
    return <WrappedComponent {...props} />;
  };
}

HOC

Example: Enhancing Components

Let’s create a practical HOC to enhance a component with additional functionality—such as adding extra props:

// A HOC that adds an extra `extraProp` to the component
function withExtraProp(WrappedComponent) {
  return function(props) {
    return <WrappedComponent extraProp="This is an extra prop" {...props} />;
  };
}

// Functional component
function MyComponent(props) {
  return <div>{props.extraProp}</div>;
}

// Enhanced component using HOC
const EnhancedComponent = withExtraProp(MyComponent);

HOC

Using HOCs with Hooks

In modern React development, hooks often replace the need for HOCs, as they are a more straightforward way to reuse stateful logic between components. However, HOCs are still useful for component logic that isn’t related to state or effects, especially when working with class components or for certain kinds of cross-cutting concerns.

Here's how a HOC might interact with a functional component using hooks:

HOC

// HOC that logs component updates
function withLogger(WrappedComponent) {
  return function(props) {
    useEffect(() => {
      console.log('Component updated:', props);
    }, [props]);

    return <WrappedComponent {...props} />;
  };
}

// Functional component
function MyComponent({ name }) {
  return <div>Hello, {name}!</div>;
}

// Enhanced component using HOC
const LoggedComponent = withLogger(MyComponent);

Render Props 

The Render Props pattern in React is a technique for sharing code between components using a prop whose value is a function. It allows you to pass the inner workings of one component into another by means of a prop—commonly named render or children. This pattern gives more flexibility in using the shared logic while keeping the component structure clean and readable.

 

The basic idea behind render props is to make a component capable of rendering something based on a function prop. This function is used to dynamically determine what to render.

Render Props 

Basic Structure of Render Props

A component with a render prop takes a function that returns a React element and calls it instead of implementing its own render logic.

// A basic component with render props
function DataProvider({ render }) {
  const data = "Data from some API";
  // Call the render prop, injecting the component's own data
  return render(data);
}

Render Props 

Advantages of Render Props

  • Flexibility: Components can define how they use shared logic by providing a custom rendering function.
  • Reusability: The logic for behaviors like data fetching, subscriptions, or interaction tracking can be abstracted into a single component, which can be reused with different rendering implementations.
  • Composability: Render props can be combined with other patterns (like higher-order components) and used with various rendering structures, enhancing their flexibility without modifying component hierarchy.

Organize the code / SM

Organizing code in a small React project efficiently can greatly improve the maintainability and scalability of the application, even as it grows. Here’s a practical guide on how to structure your React project effectively:

Organize the code / SM

1. Directory Structure

Begin by setting up a simple and intuitive directory structure. A typical small React project might look like this:

/my-app
  /public
  /src
    /components
    /contexts
    /hooks
    /assets
    /utils
    /pages
    /App.js
    /index.js
  /package.json

Organize the code / SM

  • components: Contains all the reusable UI components like buttons, inputs, modals, etc.
  • contexts: If you’re using the Context API to manage global state, place your context definitions here.
  • hooks: For custom hooks that encapsulate some of the business logic or state management logic.
  • assets: Static files like images, fonts, and style sheets.
  • utils: Utility functions and helper modules that are used across the project.
  • pages: Represents the different views/pages of your app. Each page should correspond to a route in your app.

Organize the code / MD

Organizing the code for a medium-sized React project requires a bit more consideration to maintain scalability, readability, and ease of collaboration. As the project grows in complexity, introducing more structured practices and potentially more tools becomes important. Here’s how you can structure a medium-sized React project effectively:

Organize the code / MD

1. Directory Structure

A clear and comprehensive directory structure is crucial. Here's an example of a structure that can support a medium-sized project:

Organize the code / MD

/my-app
  /public
  /src
    /components
    /containers
    /contexts
    /hooks
    /services
    /assets
    /utils
    /pages
    /layouts
    /routes
    /store  // If using Redux or another state management library
    /App.js
    /index.js
  /config
  /scripts
  /tests
  /styles
  /package.json

Organize the code / MD

  • containers: For container components that connect presentational components to data sources or manage significant logic.
  • services: For managing API calls and external interactions.
  • layouts: Define common page layouts used throughout the app.
  • routes: Centralize routing logic, especially useful if using dynamic routing or protected routes.
  • store: If using Redux, all related files like actions, reducers, and middleware.
  • config: Global configuration files, such as setup for different environments.
  • scripts: Custom scripts for builds, deployment, or other automation.
  • tests: All test configuration, utilities, and perhaps an overarching suite of integration tests.
  • styles: Global styles, variables, mixins, and theme definitions.

Atomic Design

"Atomic Design" – methodology developed by Brad Frost for creating design systems with a clear and consistent structure. It's widely applied in web development and React projects to ensure that user interfaces are scalable, reusable, and systematic. Let’s break down how Atomic Design can be implemented in a React project.

Atomic Design

Atomic Design is structured around five levels of components:

  1. Atoms: These are the basic building blocks of a user interface, similar to HTML elements. Examples include buttons, input fields, and other basic HTML elements styled to fit the design system.

  2. Molecules: Groups of atoms bonded together to perform a specific function. This might be a search form that includes a label, input field, and a button.

  3. Organisms: Complex UI components made up of groups of molecules and possibly atoms that function together as a unit. An example could be a header that contains a logo (atom), navigation (molecule), and search form (molecule).

  4. Templates: These are page-level objects that place components into a layout and demonstrate the design’s underlying content structure. Templates are mostly concerned with layout and less with content.

  5. Pages: Practical, real-world implementations of templates. Pages apply real content to templates and articulate variations to demonstrate the final UI and test the resilience of the design system.

Atomic Design

Implementing Atomic Design in React

In a React project, you can implement Atomic Design by organizing your components according to this hierarchy. Here’s how you might structure your project:

/src
  /components
    /atoms
      Button.js
      Input.js
    /molecules
      SearchForm.js
    /organisms
      Header.js
  /templates
    HomePageTemplate.js
  /pages
    HomePage.js

MONO REPO

A monorepo is a version control strategy where code for many projects is stored in a single repository. This approach is distinct from having multiple repositories, where each project or service has its own repository. Monorepos have become popular with both small teams and large enterprises because of the streamlined development process and simplified dependency management they offer.

Benefits of Using a Monorepo

  1. Simplified Dependency Management: All projects share the same dependencies, so updating libraries across multiple projects becomes straightforward.

  2. Unified Versioning: Since all projects reside in the same repository, they can be versioned together, which simplifies release management and reduces conflicts between dependencies.

  3. Improved Collaboration: Teams can work more closely together when all code is in one place. Changes in one project that might affect others can be seen immediately by all team members, improving the communication flow.

  4. Code Reuse: It's easier to share code across projects in a monorepo because all projects have access to the same codebase. This reduces duplication and promotes consistency.

  5. Atomic Commits: Changes that span multiple projects can be committed in a single atomic commit. This makes it easier to track changes and roll back if something goes wrong.

  6. Easier Refactoring: Global refactoring can be performed with confidence because the impact of changes is visible across all projects. Tooling and Continuous Integration (CI) setups can ensure that changes do not break any part of the projects in the monorepo.

Authentication

 

Authentication in JavaScript involves verifying the identity of a user before granting access to an application or its resources. This process ensures that only authorized users can access certain parts of the application. Here’s an overview of how authentication can be implemented in JavaScript, typically in a web application context:

 

 

Authentication

 

a. Session-based Authentication

  • Server-Side Sessions: The server creates a session for the user upon login, storing session data (like user ID) in memory or a database.
  • Session ID: A session ID is sent to the client, usually stored in a cookie.
  • Validation: For each request, the client sends the session ID cookie back to the server, which validates the session ID and grants access if valid.

 

 

Authentication

b. Token-based Authentication

  • JSON Web Tokens (JWT): A popular method where the server generates a token upon user login.
  • Token Storage: The token is sent to the client, typically stored in local storage or a cookie.
  • Bearer Token: The client includes the token in the Authorization header of each request.
  • Stateless: Unlike session-based, the server does not store user sessions, as the token itself contains the user information (often encoded).

 

 

Authentication

Vulnarebilities

 

XSS Attack (Cross Site Scripting)

Cross-Site Request Forgery

 

 

Authentication

Vulnerabilities

 

The question is where to store JWT token. Basically we have to options:
1. Web Storage

2. Cookie

 

Both options have their own vulnerabilities. So probably the best approach would be to use both.

https://jerrynsh.com/all-to-know-about-auth-and-cookies/

 

The End of React.js Course.

See you on the next one! 😉 ➡️

Advanced React

By noinputsignal

Advanced React

  • 4