') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); GitHub - Lunotte/react-http-request-handler: This React library using customized hooks is aimed to help users handling HTTP requests. The request and its trigger are simply configured, then executed by Axios. Optional parameters can also be configured depending on the client needs. · GitHub
Skip to content

Repository files navigation

React Http Request Handler (RH2)

Quality Gate StatusCoverageRenovateBuild StatusMaintenanceGitHub licenseReactReact Native

French documentation

Table of Contents

Contexte

This React library using customized hooks is aimed to help users handling HTTP requests. The request and its trigger are simply configured, then executed by Axios. Optional parameters can also be configured depending on the client needs. For example :

  • Configuring the request to be executed once through our historization module
  • Configuring methods to be called in case of error Redux users will find means to dispatch the request’s result, whether it was successfully handled or not. The response can be processed before being dispatched.

Functionalities

  • Everything Axios can already do
  • Adding a global configuration (instance management, HTTP error handling, request filtering, .. etc)
  • Coupling with redux
  • Allowing less code production
  • Easily cancel a request

Installation

Using npm :

$ npm install react-http-request-handler

Using yarn :

$ yarn add react-http-request-handler

Configurations

In the project sources, there is a folder named example in which you can see configuration examples (be careful, it's a bit of a mess...).

Library usage

You can initialize your application by :

Using a wrapper wherein the initial configuration is parametrized :

import{Rh2Initializer,Rh2InitializationParameter}from'react-http-request-handler';constinitSettings: Rh2InitializationParameter={debugMode: true};<Rh2Initializerrh2Settings={initSettings}><App/></Rh2Initializer>

Or by using a service later on :

import{Rh2InitializationParameter,rh2ConfigService}from'react-http-request-handler';constinitSettings: Rh2InitializationParameter={debugMode: true};rh2ConfigService.initializeParameters(initSettings);

Finally, if you do not initialize the app, a default instance is used.

If a new instance configuration is injected during runtime, the old one and its injectors are deactivated.

Using two hooks

Hooks without preloading

constaxiosConfig: AxiosRequestConfig={url: `https://jsonplaceholder.typicode.com/todos/1`,method: 'GET'};constconfiguration: Rh2EffectAxiosConfigHandler={axiosRequestConfig: axiosConfig};consttest=useRh2WithParameters(configuration);console.log(test);

Log result will be :

{loading: false,data: {userId: 1,id: 1,title: "delectus aut autem",completed: false}}
Other example :
constApp=()=>{constinitSettings: Rh2InitializationParameter={axiosConfig: [{key: 'Test1',axiosConfig: {baseURL: 'https://www.google.com/',method: 'POST'},defaultInterceptor: true,headerUrl: [{key: 'CleDeTest',value: 'value to test'}]},{key: 'Test2',axiosConfig: {baseURL: 'https://jsonplaceholder.typicode.com'},defaultInterceptor: false,headerUrl: []}],debugMode: true};return(<Providerstore={Store}><Rh2Initializerrh2Settings={initSettings}><Navigation/></Rh2Initializer></Provider>);};
constdispatch=useDispatch();constaxiosConfig: AxiosRequestConfig={url: `/todos/1`,method: 'GET'};constconfiguration: Rh2EffectAxiosConfigHandler={axiosRequestConfig: axiosConfig,onlyResult: false,keyOfInstance: 'Test2',successHandler: (value)=>dispatch(pourTestAction(value))};useRh2WithParameters(configuration);

In configuration initialization, 2 Axios instances were created

keyOfInstance: 'Test2' process the request from instance named Test2. If Test1 or nothing is specified, the result will be different. By default, the first instance specified during initialization is used .

For this example, the parameter successHandler is used to dispatch a redux action, which get the response from the request onlyResult: false.

Following is the action processed :

{type: 'POUR_TEST_ACTION',payload: {data: {userId: 1,id: 1,title: 'delectus aut autem',completed: false},status: 200,statusText: '',headers: {
...
},config: {url: '/todos/1',method: 'get',headers: {},baseURL: 'https://jsonplaceholder.typicode.com',
...
},request: {}}}
Handling error example

If the errorHandler parameter from Rh2Initializer wrapper is ignored during initialization, you can still define an handler later on, like the following :

consttraitementErreur=(data: ResponseFetchApi)=>{letmessage;switch(data.status){case405:
message='C’est une erreur 405 !';dispatch(pourTestAction(message));break;case404:
message='C’est une erreur 404 !';dispatch(pourTestAction(message));break;default:
message='Facheux ce problème !';dispatch(pourTestAction(message));break;}};rh2ConfigService.setErrorHandler(traitementErreur);

This test was done using our previous example, while executing the request with instance Test1.

Google is not expecting requests like https://www.google.com/todos/1 : a 404 error is raised.

Action processed :

{type: 'POUR_TEST_ACTION',payload: 'C’est une erreur 404 !'}

You can do anything you want to do. We can also dispatch an action with the data contained within the arguments of traitementErreur method.

Preloaded Hook

In the next example the code is compiled, but you can write a configuration file where all configurations are defined.

Then you can call the hook useRh2WithName in your component :

constaxiosConfig: AxiosRequestConfig={url: '/search?q=champ',method: 'GET'};constconfigACharger: Rh2AxiosConfig={keyOfInstance: 'Test1',axiosRequestConfig: axiosConfig,label: GOOGLE};rh2AxiosConfigService.addConfigAxios(configACharger);consttest=useRh2WithName(GOOGLE);console.log(test);

Hook with parameters

Second argument of hooks useRh2WithName and useRh2WithParameters is used to specify what to expect from the request.

useRh2WithName(GOOGLE,{pathParams: '/to/test',params: {hat: 'red',hair: 'grey'},data: {color: 'yellow',shape: 'square'}});

Response will be :

https://www.google.com/search/to/test?hat=red&hair=grey

With key/value pairs in data property in the response body.

Depending on your use case, you can also use rh2AxiosConfigService service to do the body injection.

rh2AxiosConfigService.addBodyToConfigAxios(GOOGLE,{color: 'yellow',shape: 'square'});

Axios instance

You can use Axios generated instances, by getting it from service rh2ConfigService.

Caution : : For custom instance initialization, you have to fill in the property "defaultInterceptor" à "false"
constaxiosInstance: AxiosInstance=rh2ConfigService.getAxiosInstance('TEST2');axiosInstance.interceptors.request.use(async(config)=>{constheaderImpl=awaitgetHeader();if(headerImpl){if(config.method!=='OPTIONS'){config.headers=headerImpl;}}returnconfig;},
...
);

In the previous use case, we get TEST2 instance, then create an interceptor. This use case could be implemented for example to add a token in the request header.

If you need to configure the URL with BASIC authentication, you can follow the next example :

rh2AxiosConfigService.addAuthToConfigAxios(GOOGLE,{username: 'toto',password: 'I1€5t3nGerr€'});

Services

Rh2DirectoryService

Initialize the app :

  • Management of requests stored in memory to prevent them from being executed again
MéthodetypeDescription
hasConfigQueryParameter(url: string, method: Rh2Method, params?: Rh2Param)booleanCheck the presence of the configuration
hasConfigQueryParameterByConfigQueryParameter(parameter: ConfigQueryParameter)booleanCheck the presence of the configuration
addConfigQueryParameter(configTmp: ConfigQueryParameter)voidAdd a configuration to the directory
getConfigQueryParameters()ConfigQueryParameter[]Retrieve the list of configurations
getConfigQueryParameter(url: string, method: Rh2Method, params?: Rh2Param)ConfigQueryParameterRetrieve a specific configuration
removeQueryDirectory(axiosRequestConfig: AxiosRequestConfig)voidDelete a specific configuration
removeAllQueryDirectory()voidDelete all configurations in memory

Rh2ConfigService

Initialize the app :

  • Configures Axios instances (if no configuration is provided, a default instance is generated)
  • Configures debug mode
  • Adds a handler for request errors, which can be handled by error type and error code of the request
MethodTypeDescription
initializeParameters(parameters: Rh2InitializationParameter)voidInitialize a new configuration
setErrorHandler(treatment: (param?: any) => void)voidSet an error handler, which is used for all failed requests, unless it is overriden in the request parameters
getParameters()Rh2InitializationParameterReturn service parameters
getParametersAxiosConfigs()AxiosRequestConfigExtended[]Return configuration sent by the consumer
isdebugMode()booleanReturn true if debug mode is activated
getAxiosInstances()Rh2AxiosInstanceReturn all Axios instancei
getAxiosInstance(key: string)AxiosInstanceReturn the Axios instance specified in parameter

Rh2AxiosConfigService

Initialize the app :

  • Handle preloaded configuration
MéthodetypeDescription
getAllConfigAxios()Rh2AxiosConfig[]Return all Axios configurations
getConfigAxios(label: string)Rh2AxiosConfigReturn the Axios configuration specified in parameter
hasConfigAxios(label: string)booleanReturn true if the configuration in parameter was added
addConfigAxios(configAxios: Rh2AxiosConfig)voidAdd a new configuration in parameter
addAuthToConfigAxios(label: string, auth: { username: string, password: string })voidAdd authentication information to an existing configuration in parameter
addBodyToConfigAxios(label: string, body: T)voidAdd body information to an existing configuration in parameter
replaceConfig(label: string, configAxios: Rh2AxiosConfig)voidReplace the instance in 1st argument by the one in 2nd
removeConfigAxios(label: string)voidDelete an existing configuration, specified in parameter
removeAllConfigAxios()voidDelete all existing configurations

Http error history

Each query you will execute will have been configured beforehand, with a label or not. If a request fails, it is logged with the label as key, if not, a hash is used. For each configuration, the last error that occurred is kept (eg: error code 404, 500, etc.).

You can access the list through this method :

import{getErrorsApi}from'react-http-request-handler';getErrorsApi();

Rh2 model list

Parameters for non-preloaded requests

Rh2EffectAxiosConfigHandler
exportinterfaceRh2EffectAxiosConfigHandler{readonlykeyOfInstance?: string;readonlyaxiosRequestConfig: AxiosRequestConfig;readonlyonlyResult?: boolean;readonlyerrorHandler?: OptionalParamVoidMethodreadonlysuccessHandler?: OptionalParamVoidMethod,}

keyOfInstance keyOfInstance if the value is not provided, first generated instance is used. If only one instance was provided during configuration initialization, or if none, this field can be ignored.

axiosRequestConfig Axios configuration.

lock This is used if we want to execute once the request during runtime. This value can be updated with Rh2DirectoryService.

Caution : The request filter depends on URL, method type and params property.

onlyResult This allows to choose if the request response provides only the content of data (true), or all the configuration (false). Default is true.

successHandler This field is mandatory to get a response if there is no listener for the hook return. Example : using redux to dispatch an action.

errorHandlerIf provided, overrides Rh2ConfigService property. During debug mode, if none is provided, a message will be displayed. It can be a nominal case, unless there is no listener for the hook : in this case, you have to define an errorHandler.

Rh2EffectData
exportinterfaceRh2EffectData{readonlydata?: any;readonlyparams?: any;readonlypathParams?: any;}

data Request body.

params Request query parameter.

pathParams Request path parameters.

NB : If params and pathParams are provided, pathParams is built first.

AxiosConfig

Request configuration.

exportinterfaceRh2AxiosConfigextendsRh2EffectAxiosConfigHandler{readonlylabel: ConfigAxiosTrigger;}

label Used to find a preloaded configuration.

FetchApi

Management of request returns.

ResponseFetchApi
exportinterfaceResponseFetchApi{readonlyisSuccess: boolean;readonlyisError: boolean;readonlyresponseSuccess: AxiosResponse;readonlyresponseErreur: ErreurFetchApi;readonlystatus: number;}
ErreurFetchApi
exportinterfaceErreurFetchApi{readonlyisResponseError: boolean;readonlyisRequestError: boolean;readonlyresponseError: AxiosError;readonlyrequestError: any;readonlymessageError: string;readonlyconfig: AxiosRequestConfig;}

General configuration

Following types are used with Rh2ConfigService

Rh2InitializationParameter
exportinterfaceRh2InitializationParameter{axiosConfig?: AxiosRequestConfigExtended[];errorHandler?: (param?: any)=>void;debugMode?: boolean}
AxiosRequestConfigExtended
exportinterfaceAxiosRequestConfigExtended{key: string;axiosConfig: AxiosRequestConfig;defaultInterceptor?: boolean;headerUrl?: KeyValue<string>[];}

Rh2InitializationParameter

NomTypeDescriptionValeur par défautValeur d’exemple
axiosConfigAxiosRequestConfigExtended[]Requests executed during runtime can be preconfigured. Using a label will be needed to find the added configuration[]Example 1
debugModebooleanActivates the debug mode : more information will be loggedfalsetrue, false
errorHandlerfunctionProvides a method to be used during request failn/aExample 2

AxiosRequestConfigExtended

NomTypeDescriptionValeur par défautValeur d’exemple
keystringValue to find Axios instance and to configure requests, You have to provide the instance targeted. If none is provided, the system will use the first on addedn/a"MY_DEFAULT_KEY"
axiosConfigAxiosRequestConfigAxios configuration. If you do not know this library, you can for example set the baseURL property to point out the prefix of each URL using this instance.n/a{ baseURL: 'http://test.fr' }
defaultInterceptorbooleanIf null or true, then an interceptor will be automatically created for this instance. The headerUrl property must beprovided. You can create your own interceptor by retrieving the instance from the built-in service.
If for a specific instance a default interceptor was created, you cannot use yours.
truetrue, false
headerUrl{key: string;
value: string;}[]
Header list to be used by the interceptor[{key: 'Content-Type', value: 'application/json'}][{key: 'Content-Type', value: 'application/json'}]

Example 1 :

{key: 'Test1',axiosConfig: {baseURL: 'https://www.test.com/',method: 'GET'},defaultInterceptor: true,headerUrl: [{key: 'key',value: 'value to test'}]}

Example 2 :

consttraitementErreur=(data: ResponseFetchApi)=>{letmessage;switch(data.status){case405:
message='C’est une erreur 405 !';console.log(message);dispatch(pourTestAction(message));break;case404:
message='C’est une erreur 404 !';console.log(message);dispatch(pourTestAction(message));break;default:
message='Facheux ce problème !';console.log(message);dispatch(pourTestAction(message));break;}}constinitSettings: Rh2InitializationParameter={debugMode: true,errorHandler: (data)=>traitementErreur(data)};

Error history

Rh2ErrorsApi
interfaceRh2ErrorsApi{label: string;configuration: Rh2EffectTreatmentToManageRequest;error: ResponseFetchApi;}

Roadmap

If you have recommendations, we can analyze the need !

Table of contents generated with markdown-toc

About

This React library using customized hooks is aimed to help users handling HTTP requests. The request and its trigger are simply configured, then executed by Axios. Optional parameters can also be configured depending on the client needs.

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Used by

Contributors

Languages