Giter Site home page Giter Site logo

scrollmonitor-react's Introduction

ScrollMonitor-React

This is a React component that provides an API to the scrollMonitor. It lets you create both watchers and scroll containers.

There is now a React hooks version.

It adds all the boolean properties from a watcher to this.props and takes all the method properties as properties.

Scrollmonitor-react is two higher order components. They're functions that you pass an original component and receive a new component that adds functionality to the original.

Basic Usage

Knowing when you're in the viewport

import React from 'react';
import { Watch } from 'scrollmonitor-react';

export default Watch(class MyComponent extends React.Component {

	render () {
		var text;
		if (this.props.isInViewport) {
			text = 'I AM in the viewport!';
		} else {
			text = 'You will never see this because it gets replaced when it enters the viewport.'
		}

		return (<span>
			{text}
			{this.props.children}
		</span>);
	}
});

Doing something when a watched child enters or exits the viewport

Provide methods with the scrollMonitor event names as props to your component.

import React from 'react';

import MyWatchedComponent from './the/example/above';

export default MyParentComponent extends React.Component {

	receiveStateChange (watcher) {
		console.log('state changed!', watcher)
	}

	render () {
		return (<MyWatchedComponent stateChange={this.receiveStateChange} />)
	}
}

Avoid starting the watcher automatically

By default the watcher is started on every enhanced component, but there can be situations where you want to start the watcher later so you can set the prop autoStart to false to avoid starting the watcher automatically.

API

this.props provided to your component

  • this.props.isInViewport - true if any part of the element is visible, false if not.
  • this.props.isFullyInViewport - true if the entire element is visible [1].
  • this.props.isAboveViewport - true if any part of the element is above the viewport.
  • this.props.isBelowViewport - true if any part of the element is below the viewport.
  • this.props.lockWatcher() - locks the watcher letting you move the element but watch the same place. See the scrollMonitor's documentation for more info.
  • this.props.unlockWatcher() - unlocks the watcher.
  • this.props.startWatcher() - starts the watcher if it's not running
  • this.props.stopWatcher() - stops the watcher if it's running

1. If the element is larger than the viewport isFullyInViewport is true when the element spans the entire viewport.

Properties you provide to the component

<MyWatchedComponent
	autoStart={true|false} // Decide if watcher should start when component is mounted. Default: true
	innerRef={(el, watcher, props) => this.foo = el} // allows you to gain access to the DOM element, the watcher, and the child's props
	stateChange={(watcher, childProps) => {}} // Called when any part of the state changes.
	visibilityChange={(watcher, childProps) => {}} // when the element partially enters or fully exits the viewport.
	enterViewport={(watcher, childProps) => {}} // when the element enters the viewport.
	fullyEnterViewport={(watcher, childProps) => {}} // when the element is completely in the viewport [1].
	exitViewport={(watcher, childProps) => {}} // when the element completely leaves the viewport.
	partiallyExitViewport={(watcher, childProps) => {}} // when the element goes from being fully in the viewport to only partially [2]
>
	<h1>Child components are fine too.</h1>
</MyWatchedComponent>

All callbacks receive two arguments: the watcher and the props of the child.

1. If the element is larger than the viewport fullyEnterViewport will be triggered when the element spans the entire viewport. 2. If the element is larger than the viewport partiallyExitViewport will be triggered when the element no longer spans the entire viewport.

Scroll Containers

The ScrollContainer HOC lets you create scrollMonitor Scroll Containers. It provides a scroll container on this.props that it must pass to its children.

import React from 'react';
import { render } from 'react-dom';
import { ScrollContainer } from 'scrollmonitor-react';

import MyWatchedContainer from 'the/example/above';

// Your container gets this.props.scrollContainer, which it must pass to the child components.
var Container = ScrollContainer(ContainerComponent extends React.Component {
	render () {
		i = 1;
		return (<div className="container-scroll">
			<MyWatchedContainer scrollContainer={this.props.scrollContainer}>{i++}</MyWatchedContainer>
			{...times a million}
		</div>);
	}
}

scrollmonitor-react's People

Contributors

beholderrk avatar braposo avatar christopherparo avatar paulinhapenedo avatar stutrek avatar uniqname 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  avatar  avatar

scrollmonitor-react's Issues

questions regarding offsets

Hello again, Let me explain our use case that i am trying to use scroll monitor for, and then ask a question. (sorry, this may belong in the scrollMonitor repo)

We have a huge list of images/elements that are rendered in a grid. We want to use scroll monitor to detect when an element is fully in view, to send an analytics event saying that a specific element was in the users viewport. We also want to pre-load the images for the items that are about to come into view so that they will load before the element is in view as the user is scrolling. So if we had a 500 - 1000 pixel padding we would say "render this item because its now about to come into view, but don't send an analytic event because the user hasn't seen it yet". This could happen both with items below, and items above. (but items above will have already retrieved images from the server.

I've tried messing with offsets but the problem is that it skews the whole element being watched, so the isInView might be correct and we could start loading the image, but the isFullyInView is incorrect, because if the element is stretched enough, to say 500px, there is a very small window that in the middle of the view port that would be considered "Fully in view".

See the following image, where green is marked as isFullyInViewport and the red is just isInViewport

image

I would like to not have to fork scrollmonitor and change one line of code just for this use case, so i thought I would ask and see if you have used it for this before. Or if you know of a way that we could offset for isInView and not for isFullyInView.

Any sort of feedback would be super awesome!

How do use locking?

How do we use Locking from the original library, so that we can watch the original area of the component with watcher.lock();?

Thanks!

Feature Request: PureWatch

Hi ๐Ÿ™‚

Let's say I have a class component decorated by the Watch HOC and I only want to use enterViewport and leaveViewport props from outside this component.

My component re-render each-time one of this props change when I don't even use them :

"isBelowViewport"
"isInViewport"
"isAboveViewport"
"isFullyInViewport"
"lockWatcher"
"unlockWatcher"
"startWatcher"
"stopWatcher"
"enterViewport"
"exitViewport"
"onApplicationAdded"

The main idea is to have a way to replace this : https://github.com/stutrek/scrollmonitor-react/blob/master/index.js#L159 by something like :

const omitInternalProps = obj => require('lodash.omit')(obj, [
  'autoStart',
  'innerRef',
  'stateChange',
  'visibilityChange',
  'enterViewport',
  'fullyEnterViewport',
  'exitViewport',
  'partiallyExitViewport',
]);

return (
  <Component {...omitInternalProps(this.props))}>
     {this.props.children}
  </Component>
);

@stutrek what do you think ? Did I miss something ? ๐Ÿค”

Trigger event at specific percentage view of the component

I'm able to trigger enter exit events, or the above/below events.
But I'm looking to trigger an event when scrolled, say, 75% or height of the component view.
How can I implement that?

I was able to trigger it, but the stateChange event wouldn't fire until one of the predefined events occured

Change offset values dynamically

Hi there!

I'm using this awesome lib in a project and I have a special use case. I have different offsets based on different viewports (mobile, tablet and desktop). When testing on an iPad, for instance, I go from a tablet viewport to a desktop viewport because of the breakpoints (1024px).

Right now, I'm doing the viewport measurement on componentDidMount and using that to update the offsets object saved in the component's state. That gets passed down to the watched component. I thought that this would work but seems like scrollmonitor doesn't expect new offsets value to be sent, so even when the recalculateLocation is triggered, the lib is still using the old offsets value.

Is there a way of doing that? If not, is it ok if I open a PR with that kind of feature?

Thanks!

Events - onEnter, onEnd

Are there any apis that trigger events like onEnter and onEnd? While everything works great, I required to use the common use case of the above events to trigger lazy loading and other functionality.

Doesn't run after install

Hey, excited to use this package, but i can't seem to get it working. When webpack tries to compile it gives me this error:

Error in ./~/scrollmonitor-react/index.js
Module parse failed: /<PATH>/node_modules/scrollmonitor-react/index.js Unexpected token (54:10)
You may need an appropriate loader to handle this file type.
SyntaxError: Unexpected token (54:10)
 @ ./src/components/my-component.js 27:26-56

(where is the path to node modules)

I've tried changing the index.js to include "jsnext:main": "index.js",
and "main": "dist/index.js", But that also throws an error saying scrollMonitor is undefined.

I've verified scroll monitor is installed and tried messing with a couple things but still couldn't get it to run.

React 16

peerDependencies currently specify react 15 currently. Can this be updated for react 16?

Change initial value for props

Wanting to try to have the initial value, specifically in my case the isInViewport prop, to be true on the initial load. Is there a way to do this?

I've tried avoiding the initial false value by turning off autoStart but it seems to still pass a false value first than it stops the watch.

I've also tried to set the default prop to be true but it overrides the default to false than back to true.

initial load with elements in view are set to wrong state

Everything (isInViewport, isAbove...) defaults to false. When an element loads, if its in the viewport, the corresponding states do not change to their correct state until you scroll those elements out of view and then back in.

I've tries creating a function

updateState = () => {
  this.setState({
        isInViewport: this.watcher.isInViewport,
        isAboveViewport: this.watcher.isAboveViewport,
        isBelowViewport: this.watcher.isBelowViewport,
        isFullyInViewport: this.watcher.isFullyInViewport
      })
    }

that is called by this.watcher.on('stateChange', this.updateState)

and then also calling it in the componentDidMount. This sets the states to the correct state, but right when you scroll, will change them back to all false, and will only change them back to the correct state when you scroll all the way to the top.

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.