Giter Club home page Giter Club logo

react-debounce-render's Introduction

npm Actively Maintained

React Debounce Render (now with TypeScript support)

react-debounce-render is a Higher Order Component that wraps your react components and debounces their rendering.

This method can be used to prevent extra renders when a react component rapidly receives new props by delaying the triggering of the render until updates become less frequent. Doing so will improve the overall rendering time of the application, thus improve the user experience.

It uses lodash debounce under the hood, which means that it can be configured just like lodash debounce.

Rationale:

Sometimes it's difficult, impractical or impossible to batch props updates before they're passed down to a react component, resulting in a react component being rendered too often while only the last props update might have been useful and should have triggered a rendering of the component. In these cases, debouncing the rendering of a react component may be the only solution to improve performance.

react-debounce-render is a react component that will wrap any of your react components, persist the last props update that was received while discarding the previous ones, and only rendering the wrapped component when no new updates has been received in the last few milliseconds by default. Since the debounce function used under the hood is lodash's debounce, you may also pass in a few options such as the number of milliseconds to delay the render by, a maximum delay, or whether to call render on a leading or trailing edge of the timeout.

Usage:

npm install react-debounce-render

Default usage:

import debounceRender from "react-debounce-render";

const debouncedMyReactComponent = debounceRender(MyReactComponent);

// do whatever you want with the debounced component such as connecting to a redux store:
connect((state) => {
  myProp: (state) => getProp(state);
})(debouncedMyReactComponent);

With options:

See lodash debounce for all options. Debounce render takes its parameters similarily to lodash debounce:

To trigger the debounce on the leader edge:

import debounceRender from "react-debounce-render";

const debouncedMyReactComponent = debounceRender(MyReactComponent, 100, {
  leading: true,
});

Or to ensure that at least one refresh happens every second:

import debounceRender from "react-debounce-render";

const debouncedMyReactComponent = debounceRender(MyReactComponent, 100, {
  maxWait: 1000,
});

Compose with other HOCs:

Use debounce instead of debounceRender to compose with other HOCs and some compose utility function. maximizing composability convention

import { debounce } from "react-debounce-render";
import { withStyles } from "@material-ui/core/styles";
import { compose } from "ramda";

// ...

export default compose(
  withStyles(styles),
  debounce(200, { maxWait: 400 })
)(MyReactComponent);

Changelog

8.0.2 - FEB 21 2022

  • Fixes #35: Add missing *.d.ts file. Thanks Robert Orliński for raising the issue.

8.0.0 - 8.0.1 - JAN 29 2022

  • Rewrite using TypeScript
  • Fixes #28, #24, #18, #14

7.0.1 - JAN 23 2022

  • Upgrade dependencies to fix a number of security issues

7.0.0 - AUG 22 2020

6.1.0 - JUNE 23 2020

  • Fix import of lodash.debounce. See PR #20. Thanks ReinAkane for the contribution!

6.0.0 - FEB 04 2020

  • Add support for hoisting non-react statics. See PR #16 for more details. Thanks Thomas0c for the contribution!
  • Update e2e tests to use the most recent React version
  • Drop supports for React <= 15

5.0.0 - OCT 04 2018

There is no breaking change in this version despite the major version change, this is only to highlight the fact that most of the internal implementation has changed since PR #12.

  • Removes unused lodash dependency since we're using lodash/debounce. Thanks @yched for raising the issue!
  • Using @yched cleaner implementation which doesn't use the deprecated lifecycle methods nor trigger any warning. See Issue #11.

4.0.3 - JULY 19 2018

  • Revert 4.0.2 change and use latest lodash version again, though importing lodash/debounce directly. Thanks @faizrr for raising the issue!

4.0.2 - JULY 6 2018

  • Use lodash.debounce instead of lodash to reduce built package size. Thanks @faizrr for raising the issue!

4.0.1 - APRIL 3 2018

  • Ensure that debounce is properly canceled when the component is unmounted which removes the "Warning: Can only update a mounted or mounting component." warning. Resolves Issue #5. Thanks @mjhm for the fix.

4.0.0 - NOVEMBER 20 2017

  • Move react to the peerDependencies in package.json and accept major versions greater than 15. Resolves Issue #4. Thanks @TheSharpieOne for raising the issue.

3.0.0 - AUGUST 16 2017

  • import debounceRender from 'react-debounce-render' should now consistently work. See Issue #2. Thanks @CameronAckermanSEL for raising the issue. As a result, using a destructuring assignment in the import statement (import { debounceRender } from 'react-debounce-render'') shouldn't accidentally work anymore which is a potential breaking change.

2.0.0 - JULY 31 2017

  • Module isn't built as standalone before being published to npm, resulting in a cleaner and lighter package. Also removes non lib related files from the package. See PR #1. Thanks @wbazant for the contribution.

1.0.0 - JUNE 25 2017

  • debounces a React component's render method()
  • includes e2e tests and documentation

react-debounce-render's People

Contributors

dependabot[bot] avatar meclav avatar mjhm avatar podefr avatar thomas0c avatar wbazant avatar yched avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

react-debounce-render's Issues

full Typescript support

This may just be something stupid I'm not getting (I'm not that skilled with HOCs), but here's my issue. I have a component declared in Typescript like this.

class DataGrid extends React.Component<DataGridProps>

I can export it like this:

const debouncedComponent = debounceRender(DataGrid, 1000, {})

It seems to work. But when I import and use this version in a TSX, I lose all typing on the properties. I've tried the Typescript version 'react-debounce-render' but no luck there either.

How can I accomplish this?

Revert module.exports to export defaultl

The change in the way the debounceRender function is exported (from export default to module.exports) has broken importing of the debounceRender, and is inconsistent with the documentation.

Now instead of import debounceRender from 'react-debounce-render';, imports must be import { debounceRender } from 'react-debounce-render';.

This isn't that big of a deal if you're only importing this once or twice, but if it is used pervasively, this creates a lot of extra work. Furthermore, because this repo is not using tags, there's not a great way to lock reliably to a particular version.

It is true that the readme said that "the extra default would be removed" but it wasn't actually necessary in the first place, and said nothing about the import changing.

My code was


export default debounceRender(MyComponent);```

and this worked great without the `default` in the example. 

Please do one of the folllowing:
1. Revert the export to use `export default` like before.
2. Update the documentation to show correct importing of the function.

Make composable with lodash.flowRight & ramda.compose

Hi, debounceRender is great, just wished it was composable.
I'm currently wrapping debounceRender so it can be used with compose.

<--- wrapper --->
import debounceRender from 'react-debounce-render';

export const debounce = (wait = 0, options = {}) => component =>  
  debounceRender(component, wait, options);

<--- example usage --->
export default compose(
  withStyles(styles), 
  connect(
    mapStateToProps,  
    mapDispatchToProps
  ),  
  debounce(200, {maxWait: 400})
)(SomeComponent);

react docs: higher-order-components.html#convention-maximizing-composability

Is it working for functional components?

I'm trying to test it with functional components, but don't seem to notice any effect.

import { useEffect, useState } from 'react';
// @ts-ignore
import debounceRender from 'react-debounce-render';

export function Debounce() {
	const [counter, setCounter] = useState(0);

	useEffect(() => {
		window.requestAnimationFrame(() => {
			setCounter(counter + 1);
		});
	});

	return <p>{counter}</p>;
}

export default debounceRender(Debounce, 1000, { maxWait: 1000 });

In my tests it keeps counting every frame. Desired effect: counting once per second. Using React 17.0.1.
What's wrong?

v 8.0.2 won't work in jest tests while 7.0.1 did: Jest encountered an unexpected token

In my create-react-app app (not Typescript) I use jest for tests. With 7.0.1 this works, but with 8.0.2 tests fail for components that use react-debounce-render.

Perhaps this is a jest configuration issue, but I still like to ask if react-debounce-render has been packaged/built/minified the right way in the npm package?

The reason I'm asking is the output from the test and the actual source in node_modules\react-debounce-render:

Jest encountered an unexpected token

Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.
....

C:\dev\app\node_modules\react-debounce-render\dist\index.js:1
({"Object.":function(module,exports,require,__dirname,__filename,jest){import React, { Component } from 'react';
^^^^^^
SyntaxError: Cannot use import statement outside a module

I compared the old version's node_modules\react-debounce-render\lib\index.js and it is very different. It does not import React but starts like this:

"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports["default"] = exports.debounce = void 0;

Thanks!

React 16

Please support react 16 in your package.json. You also might want to consider moving react to a peerDependency.

Lack of TS support while installing `react-debounce-render` from `npm`.

Hello!

I wanted to check how the library works since it looks like something that exactly and quickly solves my current challenge but after installing it from npm (version 8.0.1), as I see TS declarations are not included in downloaded package.

Is there something not right with the package published on npm or I don't know about something?

Thank you in advance :)

Add support for react 18

Currently react 17 is a peer dependency. I think it should work fine with react 18 without changing the code.

Throttle rather than debounce?

With debounce, you can get 'starvation' where new events keep arriving, preventing you from ever re-rendering.

lodash.throttle allows one re-render per 'wait' period, which I think would still achieve the performance aims of this library without allowing the UI to get stuck.

Typescript support

I use typescript for react projects. If this project can be added to DefinitelyTyped we can

npm install @types/react-debounce-render

and use this awesome package in typescript projects.

Decorator-friendly higher-order component

With only a few extra hundred bytes, this library could include a higher-order component that is decorator-friendly. It would also then have the same method signature as react-redux's connect, React DnD, and other higher-order components: options => Component => func(Component, options)

import debounceRender from 'react-debounce-render';

export function debounceComponent(...args) {
  return function(Component) {
    return debounceRender(Component, ...args);
  }
}

Then you can attach to a component like:

@connect(state => { prop: state.prop })
@debounceComponent(100, { trailing: true })
export default MyComponent extends Component {}

Even if you don't want to use this as a decorator, making the component the sole argument to a bunch of applied partials allows you to export a reusable debouncer with custom options, like:

const myDebouncer = debounceComponent(100, { trailing: true });
export const myDebouncer;

Not a big deal if it's not included in the library, as I'll be using that myself... but I thought it could be helpful for other people as well. Thanks for this great utility!

[Question] Should this work with react-native?

I tested it and doesn't seem to work, tested having a setinterval with a lower value (100m) than the debounce value(1000ms), and with a console log on the render and it was being called every 100 ms

README inaccurate with { leading: false }?

To trigger the debounce on the leader edge:
import debounceRender from 'react-debounce-render';
const debouncedMyReactComponent = debounceRender(MyReactComponent, 100, { leading: false });

Should it be { leading: true } maybe?

Does this repo use MIT license?

Hello!

I noticed the NPM package for this tool uses MIT license. Could we have that license added to this repo as well?

Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.