Coder Social home page Coder Social logo

jsonkao / react-scrollama Goto Github PK

View Code? Open in Web Editor NEW
378.0 5.0 29.0 9.78 MB

Simple scrollytelling with the IntersectionObserver in React.

Home Page: https://jsonkao.github.io/react-scrollama

License: MIT License

JavaScript 90.93% HTML 9.07%
scrollytelling react intersection-observer

react-scrollama's Issues

`defaultProps` warning

As of React #25699, usage of defaultProps will result in a warning:

Support for defaultProps will be removed from function components in a future major release. Use JavaScript default parameters instead.

This impacts the Scrollama and Step component.

Resizing should be more exposed to the user

Right now, React Scrollama simply adds Scrollama.handleResize as a resize event to the window. Ideally, users should be able to throttle this resizing. It would also be great to just be able to call it somehow after updating DOM/Step elements.

Call for maintainers

Hi, so I've gotten super slow at responding to issues and pull requests. I'm tagging all the beautiful people who have helped make React Scrollama possible today. Would anyone like to become a maintainer with me? It would involve responding to issues and PRs faster than my current average time (1 month lol.. sorry).

@maerzhase @fschwander @davidnmora @tuckergordon

Sorry if I forgot anyone!

2.0.3-beta breaks next.js (throws error under ssr, no workaround)

Version 2.3.0-beta.0 introduces an incompatibility with next.js SSR. As v2.3.0-beta.0 fixes other dealbreaker issues (#19 (comment)) this is a blocker problem for me.

Overview

  1. Under next.js, after upgrading to 2.3.0-beta.0, previously working code now throws the error
Server Error 
ReferenceError: window is not defined
  1. There's a standard workaround for this sort of problem - using dynamic imports. However if you attempt this (which btw also works as expected under 2.2.16 even though there's no need for it) with 2.3.0-beta.0 you get a Scrollama error
Unhandled Runtime Error 
SyntaxError: Failed to construct 'IntersectionObserver': rootMargin must be specified in pixels or percent
  1. Similar next.js workarounds (eg using process.browser) also generate the same error.

So at present it looks like using the library with next.js is not possible at all.

Steps to reproduce 1 (window error)

(the no-frills example from the Readme, unmodified):

pages/index.js

import React, { useState } from 'react';
import { Scrollama, Step } from 'react-scrollama';

const ScrollamaDemo = () => {
  const [currentStepIndex, setCurrentStepIndex] = useState(null);

  // This callback fires when a Step hits the offset threshold. It receives the
  // data prop of the step, which in this demo stores the index of the step.
  const onStepEnter = ({ data }) => {
    setCurrentStepIndex(data);
  };

  return (
    <div style={{ margin: '50vh 0', border: '2px dashed skyblue' }}>
      <div style={{ position: 'sticky', top: 0, border: '1px solid orchid' }}>
        I'm sticky. The current triggered step index is: {currentStepIndex}
      </div>
      <Scrollama onStepEnter={onStepEnter} debug>
        {[1, 2, 3, 4].map((_, stepIndex) => (
          <Step data={stepIndex} key={stepIndex}>
            <div
              style={{
                margin: '50vh 0',
                border: '1px solid gray',
                opacity: currentStepIndex === stepIndex ? 1 : 0.2,
              }}
            >
              I'm a Scrollama Step of index {stepIndex}
            </div>
          </Step>
        ))}
      </Scrollama>
    </div>
  );
};

export default ScrollamaDemo;

Steps to reproduce 2 (IntersectionObserver error)

pages/index.js

import React, {useState} from "react"
import dynamic from 'next/dynamic'

const ScrollamaDemo = dynamic(
	() => import('../components/ScrollamaDemo'),
	{ ssr: false }
)

const Page = () => 
	<div><ScrollamaDemo/></div>

export default Page

components/ScrollamaDemo.js

import React, {useState} from "react"
import { Scrollama, Step } from 'react-scrollama'

const ScrollamaDemo = () => {
  const [currentStepIndex, setCurrentStepIndex] = useState(null);
  const onStepEnter = ({ data }) => {
    setCurrentStepIndex(data);
  };

  return (
    <div style={{ margin: '50vh 0', border: '2px dashed skyblue' }}>
      <div style={{ position: 'sticky', top: 0, border: '1px solid orchid' }}>
        I'm sticky. The current triggered step index is: {currentStepIndex}
      </div>
      <Scrollama onStepEnter={onStepEnter} debug>
        {[1, 2, 3, 4].map((_, stepIndex) => (
          <Step data={stepIndex} key={stepIndex}>
            <div
              style={{
                margin: '50vh 0',
                border: '1px solid gray',
                opacity: currentStepIndex === stepIndex ? 1 : 0.2,
              }}
            >
              I'm a Scrollama Step of index {stepIndex}
            </div>
          </Step>
        ))}
      </Scrollama>
    </div>
  )
}

export default ScrollamaDemo

Update peerDependencies - allow React 17 and 18

Right now, the versions of react and react-dom required are ^16.8.0. However, this library should work fine with React 17 and React 18 (both of which are allowed in the react-intersection-observer dependency.

NPM v8 is enforcing peerDependencies more strictly than previous versions, so trying to install this on a React 17 project errors. I don't think there's anything in the library that would preclude it from working on newer versions of React. Can we add those versions to this package's peer dependencies?

Forgot default Props for offset in Scrollama.js

Hey there!

First of all: thanks for the great npm package. <3

It seems that you forgot the default props of of offset equals 0.3 in Scrollama.js (as described in your documentation).

Best, Fabian

React.Children.only expected to receive a single React element child

If you try to recreate the example in the README, you get this error:

React.Children.only expected to receive a single React element child

The problem is that <Step> is taking text nodes in the example:

        <Scrollama onStepEnter={this.onStepEnter}>
          <Step data={1} key='1'>
            step 1
          </Step>
          <Step data={2} key='2'>
            step 2
          </Step>
        </Scrollama>

However, if you replace the text nodes any element, then everything works correctly:

        <Scrollama onStepEnter={this.onStepEnter}>
          <Step data={1} key='1'>
            <div>step 1</div>
          </Step>
          <Step data={2} key='2'>
            <div>step 2</div>
          </Step>
        </Scrollama>

React.Children.only(children) throws with a text node: https://github.com/jsonkao/react-scrollama/blob/master/src/Step.js#L25

I don't know if you want to allow text nodes, or update the README to wrap the text in elements.

Dynamic contents don't get updated

Relevalent snippet

let jsx=[];
for (let i=0;i<N;i++){
   jsx.push(<Step data={{step:i}}><div> {i}</div></Step>);
}
return(<Scrollama onStepEnter={onStepEnter}>{jsx}</Scrollama>);

This works well while N is the same (or smaller) than the original. But if you change N to a larger number afterwards, it will only work up to that number.

Using React.Fragment (empty tags) causes Runtime Error. Failed to construct 'IntersectionObserver': rootMargin must be specified in pixels or percent.

Basically, this works:

<Scrollama>
    <Step data={1}>
      <div style={{ height: "400px" }}>1</div>
    </Step>
    <Step data={2}>
      <div style={{ height: "400px" }}>2</div>
    </Step>
</Scrollama>

But this throws runtime error:

<Scrollama>
  <>
    <Step data={1}>
      <div style={{ height: "400px" }}>1</div>
    </Step>
    <Step data={2}>
      <div style={{ height: "400px" }}>2</div>
    </Step>
  </>
</Scrollama>

Full Error:

Failed to construct 'IntersectionObserver': rootMargin must be specified in pixels or percent.
    at new e.IntersectionObserver (chrome-extension://ekhagklcjbdpajgpjgmbionohlpdbjgc/lib/SingleFile/single-file-hooks-frames.js:1:8206)
    at createObserver (http://localhost:3000/static/js/bundle.js:41452:22)
    at observe (http://localhost:3000/static/js/bundle.js:41509:7)
    at http://localhost:3000/static/js/bundle.js:41587:27
    at http://localhost:3000/static/js/bundle.js:41683:5
    at commitAttachRef (http://localhost:3000/static/js/bundle.js:32135:24)
    at commitLayoutEffectOnFiber (http://localhost:3000/static/js/bundle.js:32016:13)
    at commitLayoutMountEffects_complete (http://localhost:3000/static/js/bundle.js:33015:13)
    at commitLayoutEffects_begin (http://localhost:3000/static/js/bundle.js:33004:11)
    at commitLayoutEffects (http://localhost:3000/static/js/bundle.js:32950:7)

This makes it a bit tricky to do array mappings, e.g.

<Scrollama>
  {[1, 2].map((i) => (
    <>
      <Step data={{ step: i, part: 1 }}>
        <div style={{ height: "400px" }}>part1</div>
      </Step>
      <Step data={{ step: i, part: 2 }}>
        <div style={{ height: "200px" }}>part2</div>
      </Step>
    </>
  ))}
</Scrollama>

A work around is to generate a rolled out array first, and then map each element to a single Step element.

Background image resolution changes

Hi @jsonkao

I am using your awesome react-scrollama npm in my project. I made the background image fixed with the css property "background-attachment: fixed" and added a scrollama component with 3 Steps over the container. Then, when I scroll up or down, the background image gets blurry except for start and end of scrolling. How can I fix it? Thank you in advance!

Rewrite using functional components and hooks

Hi there it's me again! ๐Ÿ˜ธ
I had some time to look into scrollama and react-scrollama. With the problems we previously found in e.g. #40 I started to be curious about a modern functional components and hooks approach for react-scrollama . After I did a short deep dive into both libs and the use of react-intersection-observer-hook lib, it was actually pretty easy to implement a working version.

The benefits I see in the rewrite is mainly in code maintenance (less code) and smaller bundle size. My build works as a drop-in replacement of the example and is only ~8kb instead of ~26kb.

Since i am not sure if you are at all interested in such a rewrite I wanted to open this issue before I open a PR. Just let me know if you want to integrate this as a release of this library. You can have a look at the code here:
https://github.com/maerzhase/react-scrollama/tree/feature/functional-rewrite

Since there are no tests written i am not 100% sure if I might have missed something. I tried my best to keep up with the existing API and from running the example I actually do not experience any problems.

onStepEnter isn't being called in gatsby

I'm trying to get the example working in Gatsby. The component renders, but onStepEnter is never actually called:

import React, { Component } from "react"
import { Scrollama, Step } from 'react-scrollama';

import Layout from "../components/layout"
import Head from '../components/head';

class NarrativePage extends Component {
  state = {
    data: 0,
    steps: [10, 20, 30],
    progress: 0,
  };

  onStepEnter = ({ element, data }) => {
    console.log(data);
    element.style.backgroundColor = 'lightgoldenrodyellow';
    this.setState({ data });
  };

  onStepExit = ({ element }) => {
    element.style.backgroundColor = '#fff';
  };

  onStepProgress = ({ element, progress }) => {
    this.setState({ progress });
  };

  render() {
    const { data, steps, progress } = this.state;
    
    return (
      <Layout>
        <Head title="Narrative"/>
        <div className="graphicContainer">
          <div className="scroller">
            <Scrollama
              onStepEnter={this.onStepEnter}
              onStepExit={this.onStepExit}
              progress
              onStepProgress={this.onStepProgress}
              offset={0.4}
              debug
            >
              {steps.map(value => (
                <Step data={value} key={value}>
                  <div className="step">
                    <p>step value: {value}</p>
                    {value === data && <p>{Math.round(progress * 100)}%</p>}
                  </div>
                </Step>
              ))}
            </Scrollama>
          </div>
          <div className="graphic">
            <p>{data}</p>
          </div>
        </div>
      </Layout>
    )
  }
}

export default NarrativePage;

Jest Snapshots

Howdy,

I've noticed that when I setup Jest Snapshot testing on a page that has Scrollama setup, it continually re-generating ids. E.g:

    -                 id="813dd771-d938-48ca-a2d5-0c7b82d84333"
    +                 id="588693b2-d464-4ada-8abf-b217a101d32f"

Therefore snapshot tests are always failing. Is it possible to avoid this?

Eexpects window to be defined, but now always the case

Webpack production build using Gatsby return WebpackError: ReferenceError: window is not defined.
Should make sure window is define before loading intersection-oberver. Will also make other window usage in scrollama.js works with that mechanic.

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.