


What are React higher-order components? How does it create a breadcrumb navigation?
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 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> );
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 ); }, []);
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; };
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, }); };
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>; };
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;
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) );
Q&A
If the
routes
generated byreact 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 theconnect
high-order function provided byreact-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) ) );
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.
withRouter to wrap the
return value of
connect, that is,
withRouter( connect(mapStateToProps)(({ location, routes }) => BreadcrumbsHoc(location, routes)(BreadcrumbsComponent) ) );
其实我们从这里也可以看出,高阶组件同高阶函数一样,不会对组件的类型造成任何更改,因此高阶组件就如同链式调用一样,可以任意多层包裹来给组件传入不同的属性,在正常情况下也可以随意调换位置,在使用上非常的灵活。这种可插拔特性使得高阶组件非常受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!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

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

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics

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? 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 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.

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

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 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 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 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.
