search
HomeWeb Front-endH5 TutorialDetailed analysis of the core history library in React Router

This article introduces to you a detailed analysis of the core history library in React Router. It has certain reference value. Friends in need can refer to it. I hope it will be helpful to you.

Preface

Use React to develop slightly more complex applications. React Router is almost the only choice for routing management. Although React Router has undergone four major version updates and its functions have become more and more abundant, no matter how it changes, its core dependence on the history library has not changed. Let's take a look at what functions this library with 4k stars on github provides.

HTML5 history object

Talking about the history library, do you think this word is a bit familiar? Yes, a new history object with the same name has also been added to the HTML5 specification. Let's take a look at what problems this history object is used to solve.

In the era when jQuery dominated the front-end, updating pages through ajax requests without refreshing was a very popular page processing method at that time. The prototype of SPA evolved at that time. In order to mark changes to the page so that the correct page elements can still be displayed after refreshing, the hash value of the URL is generally changed to uniquely locate the page. But this brings up another problem: users cannot use forward/backward to switch pages.

In order to solve this problem, the history object came into being. When the URL or hash of the page changes, the browser will automatically push the new URL into the history object. A state array is maintained inside the history object to record changes in the URL. When the browser performs a forward/backward operation, it actually calls the corresponding method of the history object (forward/back) to retrieve the corresponding state to switch pages.

In addition to operating the URL, the history object also provides two methods that can update the internal state without operating the URL, namely pushState and replaceState. You can also store additional data in the state, and then retrieve it through event.state in the onpopstate event. If you want a deeper understanding of the history object, you can refer to here, and here.

The relationship between the history library and the HTML5 history object

Let’s go back and look at the history library. It essentially does the following 4 things:

  1. Learns from the concept of HTML5 history object, and extends some functions based on it

  2. Provides 3 types of history: browserHistory, hashHistory, memoryHistory, and maintains a unified API

  3. Supports the publish/subscribe function. When the history changes, the subscription function can be automatically triggered

  4. Provides practical functions such as jump interception, jump confirmation and basename

Let’s compare some similarities and differences between the two APIs. The following is the history library:

const history = {
    length,        // 属性,history中记录的state的数量
    action,        // 属性,当前导航的action类型
    location,      // 属性,location对象,封装了pathname、search和hash等属性
    push,          // 方法,导航到新的路由,并记录在history中
    replace,       // 方法,替换掉当前记录在history中的路由信息
    go,            // 方法,前进或后退n个记录
    goBack,        // 方法,后退
    goForward,     // 方法,前进
    canGo,         // 方法,是否能前进或后退n个记录
    block,         // 方法,跳转前让用户确定是否要跳转
    listen         // 方法,订阅history变更事件
  };

The following is the HTML5 history object:

const history = {
    length,         // 属性,history中记录的state的数量
    state,          // 属性,pushState和replaceState时传入的对象
    back,           // 方法,后退
    forward,        // 方法,前进
    go,             // 方法,前进或后退n个记录
    pushState,      // 方法,导航到新的路由,并记录在history中
    replaceState    // 方法,替换掉当前记录在history中的路由信息
}

// 订阅history变更事件
window.onpopstate = function (event) {
    ...
}

It can be seen from the comparison that the relationship between the two is very close. The history library can be said to be the history object. A superset of , which is a more powerful history object.

createHashHistory source code analysis

Below, we take one of the three history types, hashHistory, as an example to analyze the history source code and see what it does. Let’s first look at how it handles hash changes.

// 构造hashHistory对象
const createHashHistory = (props = {}) => {
    ...
    const globalHistory = window.history;    // 引用HTML5 history对象
    ...
    // transitionManager负责控制是否进行跳转,以及跳转后要通知到的订阅者,后面会详细讨论
    const transitionManager = createTransitionManager();
    ...
    // 注册history变更回调的订阅者
    const listen = listener => {
        const unlisten = transitionManager.appendListener(listener);
        checkDOMListeners(1);

        return () => {
            checkDOMListeners(-1);
            unlisten();
        };
    };
    
    // 监听hashchange事件
    const checkDOMListeners = delta => {
        listenerCount += delta;

        if (listenerCount === 1) {
            window.addEventListener(HashChangeEvent, handleHashChange);
        } else if (listenerCount === 0) {
            window.removeEventListener(HashChangeEvent, handleHashChange);
        }
    };
    
    // hashchange事件回调
    const handleHashChange = () => {
        ...
        // 构造内部使用的location对象,包含pathname、search和hash等属性
        const location = getDOMLocation();    
        ...
        handlePop(location);
    };
    
    // 处理hash变更逻辑
    const handlePop = location => {
        ...
        const action = "POP";
        // 给用户展示确认跳转的信息(如果有的话),确认后通知订阅者。如果用户取消跳转,则回退到之前状态
        transitionManager.confirmTransitionTo(location, action, getUserConfirmation, ok => {
            if (ok) {
                setState({action, location});    // 确认后通知订阅者
            } else {
                revertPop(location);             // 取消则回退到之前状态
            }
        });
    };
    
    // 更新action,location和length属性,并通知订阅者
    const setState = nextState => {
        Object.assign(history, nextState);

        history.length = globalHistory.length;

        transitionManager.notifyListeners(history.location, history.action);
    };
    ...
}

The above is the logic for handling passive hash changes. In one sentence, it can be summarized as follows: subscribe to the hash change event, determine whether the change is really needed, update your own attributes if a change is needed, and notify the subscriber. If no change is needed, Go back to the previous state.

Let’s take a look at what the transitionManager does, focusing on the content related to publishing/subscribing, and ignoring the content related to the user confirmation jump.

const createTransitionManager = () => {
    ...
    // 内部维护的订阅者列表
    let listeners = [];

    // 注册订阅者
    const appendListener = fn => {
        let isActive = true;

        const listener = (...args) => {
            if (isActive) fn(...args);
        };

        listeners.push(listener);

        return () => {
            isActive = false;
            listeners = listeners.filter(item => item !== listener);
        };
    };

    //通知订阅者
    const notifyListeners = (...args) => {
        listeners.forEach(listener => listener(...args));
    };
    ...
}

The code here is clear at a glance, it is to maintain a list of subscribers and notify the relevant functions when the hash changes.

The above is the content related to passive update when hash changes. Let's take a look at the code related to active update. Taking push as an example, replace is similar.

const push = (path, state) => {
    ...
    const action = "PUSH";
    const location = createLocation(path, undefined, undefined, history.location);

    transitionManager.confirmTransitionTo(location, action, getUserConfirmation, ok => {
        if (!ok)     // 如果取消,则不跳转
            return;
        ...
        pushHashPath(encodedPath);        // 用新的hash替换到url当中
        ...
        setState({action, location});     // 更新action,location和length属性,并通知订阅者

    });
};

// 用新的hash替换到url当中
const pushHashPath = path => (window.location.hash = path);

When the browser performs forward and backward operations, the history library is actually implemented by operating the HTML5 history object.

const globalHistory = window.history;

const go = n => {
    ...
    globalHistory.go(n);
};

const goBack = () => go(-1);

const goForward = () => go(1);

When window.history.go is called, the hash will change, triggering the hashchange event, and then the history library will notify the relevant subscribers of the change.

Summary

This article provides a more in-depth introduction to the history library that React Router core relies on. Starting from the new history object in HTML5, we compare its inextricable relationship with the history library, and use hashHistory as an example to analyze the implementation details of its code in detail.

Finally, let’s review what the history library has done:

  1. Learn from the concept of HTML5 history object and expand some functions on its basis

  2. Provides 3 types of history: browserHistory, hashHistory, memoryHistory, and maintains a unified API

  3. ##Supports publish/subscribe function, when the history changes At this time, the subscription function can be automatically triggered

  4. Provides practical functions such as jump interception, jump confirmation and basename

Although the history library is React Router's core dependency, but it has no dependency on React itself. If your project has a history manipulation scenario, you can also introduce it into the project.

Related recommendations:

How to use h5 to implement react drag and drop sorting components (with code)

How to solve the collapse problem of margin-top in HTML5 (Code attached)

What are the tags and common rules in HTML5? Introduction to html5 tags and rules


The above is the detailed content of Detailed analysis of the core history library in React Router. For more information, please follow other related articles on the PHP Chinese website!

Statement
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
H5: New Features and Capabilities for Web DevelopmentH5: New Features and Capabilities for Web DevelopmentApr 29, 2025 am 12:07 AM

H5 brings a number of new functions and capabilities, greatly improving the interactivity and development efficiency of web pages. 1. Semantic tags such as enhance SEO. 2. Multimedia support simplifies audio and video playback through and tags. 3. Canvas drawing provides dynamic graphics drawing tools. 4. Local storage simplifies data storage through localStorage and sessionStorage. 5. The geolocation API facilitates the development of location-based services.

H5: Key Improvements in HTML5H5: Key Improvements in HTML5Apr 28, 2025 am 12:26 AM

HTML5 brings five key improvements: 1. Semantic tags improve code clarity and SEO effects; 2. Multimedia support simplifies video and audio embedding; 3. Form enhancement simplifies verification; 4. Offline and local storage improves user experience; 5. Canvas and graphics functions enhance the visualization of web pages.

HTML5: The Standard and its Impact on Web DevelopmentHTML5: The Standard and its Impact on Web DevelopmentApr 27, 2025 am 12:12 AM

The core features of HTML5 include semantic tags, multimedia support, offline storage and local storage, and form enhancement. 1. Semantic tags such as, etc. to improve code readability and SEO effect. 2. Simplify multimedia embedding with labels. 3. Offline storage and local storage such as ApplicationCache and LocalStorage support network-free operation and data storage. 4. Form enhancement introduces new input types and verification properties to simplify processing and verification.

H5 Code Examples: Practical Applications and TutorialsH5 Code Examples: Practical Applications and TutorialsApr 25, 2025 am 12:10 AM

H5 provides a variety of new features and functions, greatly enhancing the capabilities of front-end development. 1. Multimedia support: embed media through and elements, no plug-ins are required. 2. Canvas: Use elements to dynamically render 2D graphics and animations. 3. Local storage: implement persistent data storage through localStorage and sessionStorage to improve user experience.

The Connection Between H5 and HTML5: Similarities and DifferencesThe Connection Between H5 and HTML5: Similarities and DifferencesApr 24, 2025 am 12:01 AM

H5 and HTML5 are different concepts: HTML5 is a version of HTML, containing new elements and APIs; H5 is a mobile application development framework based on HTML5. HTML5 parses and renders code through the browser, while H5 applications need to run containers and interact with native code through JavaScript.

The Building Blocks of H5 Code: Key Elements and Their PurposeThe Building Blocks of H5 Code: Key Elements and Their PurposeApr 23, 2025 am 12:09 AM

Key elements of HTML5 include,,,,,, etc., which are used to build modern web pages. 1. Define the head content, 2. Used to navigate the link, 3. Represent the content of independent articles, 4. Organize the page content, 5. Display the sidebar content, 6. Define the footer, these elements enhance the structure and functionality of the web page.

HTML5 and H5: Understanding the Common UsageHTML5 and H5: Understanding the Common UsageApr 22, 2025 am 12:01 AM

There is no difference between HTML5 and H5, which is the abbreviation of HTML5. 1.HTML5 is the fifth version of HTML, which enhances the multimedia and interactive functions of web pages. 2.H5 is often used to refer to HTML5-based mobile web pages or applications, and is suitable for various mobile devices.

HTML5: The Building Blocks of the Modern Web (H5)HTML5: The Building Blocks of the Modern Web (H5)Apr 21, 2025 am 12:05 AM

HTML5 is the latest version of the Hypertext Markup Language, standardized by W3C. HTML5 introduces new semantic tags, multimedia support and form enhancements, improving web structure, user experience and SEO effects. HTML5 introduces new semantic tags, such as, ,, etc., to make the web page structure clearer and the SEO effect better. HTML5 supports multimedia elements and no third-party plug-ins are required, improving user experience and loading speed. HTML5 enhances form functions and introduces new input types such as, etc., which improves user experience and form verification efficiency.

See all articles

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

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

Integrate Eclipse with SAP NetWeaver application server.

mPDF

mPDF

mPDF is a PHP library that can generate PDF files from UTF-8 encoded HTML. The original author, Ian Back, wrote mPDF to output PDF files "on the fly" from his website and handle different languages. It is slower than original scripts like HTML2FPDF and produces larger files when using Unicode fonts, but supports CSS styles etc. and has a lot of enhancements. Supports almost all languages, including RTL (Arabic and Hebrew) and CJK (Chinese, Japanese and Korean). Supports nested block-level elements (such as P, DIV),

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Dreamweaver Mac version

Dreamweaver Mac version

Visual web development tools

EditPlus Chinese cracked version

EditPlus Chinese cracked version

Small size, syntax highlighting, does not support code prompt function