Table of Contents
What are React high-order components
Benefits of using React high-order components
Implement a high-order component by myself
Q&A
Home Web Front-end JS Tutorial What are React higher-order components? How does it create a breadcrumb navigation?

What are React higher-order components? How does it create a breadcrumb navigation?

Oct 19, 2022 pm 07:33 PM
react javascript

What are React higher-order components? Let’s talk about how to use React high-order components to create a breadcrumb navigation. I hope it will be helpful to everyone!

What are React higher-order components? How does it create a breadcrumb navigation?

What are React high-order components

React high-order components wrap React components that need to be modified in the form of high-order functions , and return the React component after processing is completed. React high-order components are used very frequently in the React ecosystem, such as withRouter in react-router and connect in react-redux Many APIs are implemented in this way.

Benefits of using React high-order components

At work, we often have many page requirements with similar functions and duplicate component codes. Usually we can completely copy The function is implemented in one pass of code, but the maintainability of the page will become extremely poor, and the same components in each page need to be changed. Therefore, we can extract the common parts, such as accepting the same query operation results, wrapping the same label outside the component, etc., make a separate function, and pass in different business components as sub-component parameters, and this function It will not modify the sub-component, but wrap the sub-component in the container component through combination. It is a pure function without side effects, so that we can decouple this part of the code without changing the logic of these components, and improve the code Maintainability.

Implement a high-order component by myself

In front-end projects, breadcrumb navigation with link pointing is very commonly used, but because breadcrumb navigation requires manual maintenance of all directories An array of mappings between paths and directory names, and all the data here can be obtained from the routing table of react-router, so we can start from here to implement a high-order component for breadcrumb navigation.

First, let’s take a look at the data provided by our routing table and the data required by the target breadcrumb component:

// 这里展示的是 react-router4 的route示例
let routes = [
  {
    breadcrumb: '一级目录',
    path: '/a',
    component: require('../a/index.js').default,
    items: [
      {
        breadcrumb: '二级目录',
        path: '/a/b',
        component: require('../a/b/index.js').default,
        items: [
          {
            breadcrumb: '三级目录1',
            path: '/a/b/c1',
            component: require('../a/b/c1/index.js').default,
            exact: true,
          },
          {
            breadcrumb: '三级目录2',
            path: '/a/b/c2',
            component: require('../a/b/c2/index.js').default,
            exact: true,
          },
      }
    ]
  }
]

// 理想中的面包屑组件
// 展示格式为 a / b / c1 并都附上链接
const BreadcrumbsComponent = ({ breadcrumbs }) => (
  <div>
    {breadcrumbs.map((breadcrumb, index) => (
      <span key={breadcrumb.props.path}>
        <link to={breadcrumb.props.path}>{breadcrumb}</link>
        {index < breadcrumbs.length - 1 && <i> / </i>}
      </span>
    ))}
  </div>
);
Copy after login

Here we can see that there are three types of data that the breadcrumb component needs to provide. One is the path of the current page, the other is the text carried by the breadcrumbs, and the other is the navigation link of the breadcrumbs.

First of all, we can use the withRouter high-order component package provided by react-router, which allows the sub-component to obtain the location attribute of the current page and thereby obtain the page path.

The latter two require us to operate routes. First, flatten the data provided by routes into the format required for breadcrumb navigation. We can use a function to implement it.

/**
 * 以递归的方式展平react router数组
 */
const flattenRoutes = arr =>
  arr.reduce(function(prev, item) {
    prev.push(item);
    return prev.concat(
      Array.isArray(item.items) ? flattenRoutes(item.items) : item
    );
  }, []);
Copy after login

Then put the flattened directory path mapping and the current page path into the processing function to generate a breadcrumb navigation structure.

export const getBreadcrumbs = ({ flattenRoutes, location }) => {
  // 初始化匹配数组match
  let matches = [];

  location.pathname
    // 取得路径名,然后将路径分割成每一路由部分.
    .split('?')[0]
    .split('/')
    // 对每一部分执行一次调用`getBreadcrumb()`的reduce.
    .reduce((prev, curSection) => {
      // 将最后一个路由部分与当前部分合并,比如当路径为 `/x/xx/xxx` 时,pathSection分别检查 `/x` `/x/xx` `/x/xx/xxx` 的匹配,并分别生成面包屑
      const pathSection = `${prev}/${curSection}`;
      const breadcrumb = getBreadcrumb({
        flattenRoutes,
        curSection,
        pathSection,
      });

      // 将面包屑导入到matches数组中
      matches.push(breadcrumb);

      // 传递给下一次reduce的路径部分
      return pathSection;
    });
  return matches;
};
Copy after login

Then for each breadcrumb path part, generate the directory name and attach a link attribute pointing to the corresponding routing location.

const getBreadcrumb = ({ flattenRoutes, curSection, pathSection }) => {
  const matchRoute = flattenRoutes.find(ele => {
    const { breadcrumb, path } = ele;
    if (!breadcrumb || !path) {
      throw new Error(
        'Router中的每一个route必须包含 `path` 以及 `breadcrumb` 属性'
      );
    }
    // 查找是否有匹配
    // exact 为 react router4 的属性,用于精确匹配路由
    return matchPath(pathSection, { path, exact: true });
  });

  // 返回breadcrumb的值,没有就返回原匹配子路径名
  if (matchRoute) {
    return render({
      content: matchRoute.breadcrumb || curSection,
      path: matchRoute.path,
    });
  }

  // 对于routes表中不存在的路径
  // 根目录默认名称为首页.
  return render({
    content: pathSection === '/' ? '首页' : curSection,
    path: pathSection,
  });
};
Copy after login

Then the render function generates the final single breadcrumb navigation style. A single breadcrumb component needs to provide the render function with the two props of the path path that the breadcrumb points to, and the breadcrumb content mapping content.

/**
 *
 */
const render = ({ content, path }) => {
  const componentProps = { path };
  if (typeof content === 'function') {
    return <content {...componentProps} />;
  }
  return <span {...componentProps}>{content}</span>;
};
Copy after login

With these functions, we can implement a React higher-order component that can pass the current path and routing properties to the wrapped component. Pass in a component and return a new and identical component structure, so that it will not damage any functions and operations outside the component.

const BreadcrumbsHoc = (
  location = window.location,
  routes = []
) => Component => {
  const BreadComponent = (
    <Component
      breadcrumbs={getBreadcrumbs({
        flattenRoutes: flattenRoutes(routes),
        location,
      })}
    />
  );
  return BreadComponent;
};
export default BreadcrumbsHoc;
Copy after login

The method of calling this high-order component is also very simple. You only need to pass in the current path and the routes attribute generated by the entire react router.
As for how to obtain the current path, we can use the withRouter function provided by react router. Please refer to the relevant documentation for how to use it.
It is worth mentioning that withRouter itself is a high-order component that can provide several routing attributes including the location attribute for the wrapped component. Therefore, this API can also be used as a good reference for learning higher-order components.

withRouter(({ location }) =>
  BreadcrumbsHoc(location, routes)(BreadcrumbsComponent)
);
Copy after login

Q&A

  • If the routes generated by react router are not manually maintained by themselves, they do not even exist locally , but it is pulled through requests and stored in redux. When wrapped through the connect high-order function provided by react-redux, the route will not cause the package to change. Crumb component updated. The usage is as follows:

function mapStateToProps(state) {
  return {
    routes: state.routes,
  };
}

connect(mapStateToProps)(
  withRouter(({ location }) =>
    BreadcrumbsHoc(location, routes)(BreadcrumbsComponent)
  )
);
Copy after login

This is actually a bug of the connect function. Because the connect high-order component of react-redux will implement the shouldComponentUpdate hook function for the incoming parameter component, the update-related life cycle function (including render) will only be triggered when the prop changes, and obviously , our location object is not passed into the parameter component as prop.

The officially recommended approach is to use

withRouter to wrap the return value of connect, that is,

withRouter(
  connect(mapStateToProps)(({ location, routes }) =>
    BreadcrumbsHoc(location, routes)(BreadcrumbsComponent)
  )
);
Copy after login

其实我们从这里也可以看出,高阶组件同高阶函数一样,不会对组件的类型造成任何更改,因此高阶组件就如同链式调用一样,可以任意多层包裹来给组件传入不同的属性,在正常情况下也可以随意调换位置,在使用上非常的灵活。这种可插拔特性使得高阶组件非常受React生态的青睐,很多开源库里都能看到这种特性的影子,有空也可以都拿出来分析一下。

The above is the detailed content of What are React higher-order components? How does it create a breadcrumb navigation?. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

WebSocket and JavaScript: key technologies for implementing real-time monitoring systems WebSocket and JavaScript: key technologies for implementing real-time monitoring systems Dec 17, 2023 pm 05:30 PM

WebSocket and JavaScript: Key technologies for realizing real-time monitoring systems Introduction: With the rapid development of Internet technology, real-time monitoring systems have been widely used in various fields. One of the key technologies to achieve real-time monitoring is the combination of WebSocket and JavaScript. This article will introduce the application of WebSocket and JavaScript in real-time monitoring systems, give code examples, and explain their implementation principles in detail. 1. WebSocket technology

PHP, Vue and React: How to choose the most suitable front-end framework? PHP, Vue and React: How to choose the most suitable front-end framework? Mar 15, 2024 pm 05:48 PM

PHP, Vue and React: How to choose the most suitable front-end framework? With the continuous development of Internet technology, front-end frameworks play a vital role in Web development. PHP, Vue and React are three representative front-end frameworks, each with its own unique characteristics and advantages. When choosing which front-end framework to use, developers need to make an informed decision based on project needs, team skills, and personal preferences. This article will compare the characteristics and uses of the three front-end frameworks PHP, Vue and React.

Integration of Java framework and front-end React framework Integration of Java framework and front-end React framework Jun 01, 2024 pm 03:16 PM

Integration of Java framework and React framework: Steps: Set up the back-end Java framework. Create project structure. Configure build tools. Create React applications. Write REST API endpoints. Configure the communication mechanism. Practical case (SpringBoot+React): Java code: Define RESTfulAPI controller. React code: Get and display the data returned by the API.

Simple JavaScript Tutorial: How to Get HTTP Status Code Simple JavaScript Tutorial: How to Get HTTP Status Code Jan 05, 2024 pm 06:08 PM

JavaScript tutorial: How to get HTTP status code, specific code examples are required. Preface: In web development, data interaction with the server is often involved. When communicating with the server, we often need to obtain the returned HTTP status code to determine whether the operation is successful, and perform corresponding processing based on different status codes. This article will teach you how to use JavaScript to obtain HTTP status codes and provide some practical code examples. Using XMLHttpRequest

How to get HTTP status code in JavaScript the easy way How to get HTTP status code in JavaScript the easy way Jan 05, 2024 pm 01:37 PM

Introduction to the method of obtaining HTTP status code in JavaScript: In front-end development, we often need to deal with the interaction with the back-end interface, and HTTP status code is a very important part of it. Understanding and obtaining HTTP status codes helps us better handle the data returned by the interface. This article will introduce how to use JavaScript to obtain HTTP status codes and provide specific code examples. 1. What is HTTP status code? HTTP status code means that when the browser initiates a request to the server, the service

Vue.js vs. React: Project-Specific Considerations Vue.js vs. React: Project-Specific Considerations Apr 09, 2025 am 12:01 AM

Vue.js is suitable for small and medium-sized projects and fast iterations, while React is suitable for large and complex applications. 1) Vue.js is easy to use and is suitable for situations where the team is insufficient or the project scale is small. 2) React has a richer ecosystem and is suitable for projects with high performance and complex functional needs.

JavaScript and WebSocket: Building an efficient real-time search engine JavaScript and WebSocket: Building an efficient real-time search engine Dec 17, 2023 pm 10:13 PM

JavaScript and WebSocket: Building an efficient real-time search engine Introduction: With the development of the Internet, users have higher and higher requirements for real-time search engines. When searching with traditional search engines, users need to click the search button to get results. This method cannot meet users' needs for real-time search results. Therefore, using JavaScript and WebSocket technology to implement real-time search engines has become a hot topic. This article will introduce in detail the use of JavaScript

React's Role in HTML: Enhancing User Experience React's Role in HTML: Enhancing User Experience Apr 09, 2025 am 12:11 AM

React combines JSX and HTML to improve user experience. 1) JSX embeds HTML to make development more intuitive. 2) The virtual DOM mechanism optimizes performance and reduces DOM operations. 3) Component-based management UI to improve maintainability. 4) State management and event processing enhance interactivity.

See all articles