Coder Social home page Coder Social logo

Comments (22)

inspectordanno avatar inspectordanno commented on June 4, 2024 2

@jsonkao OMG!! This was the error that I was having that confused me! Have to wrap the step-child (haha pun) in a <div> if it is a React component. Got it!

I wouldn't be unopposed to having a ref exposed that I could forward to a custom component.

from react-scrollama.

gjhltn avatar gjhltn commented on June 4, 2024 1

@maerzhase man you're a star - the sandbox completely solved the mystery thank you.

Appreciate the next tips too - yes I shall do something like that - it's clearly GOT to be a client side thing 😀

once again tons of thanks for going to that extra bit of trouble. I'm really grateful.

from react-scrollama.

maerzhase avatar maerzhase commented on June 4, 2024 1

@gswirrl hej man no problem! I really enjoy contributing in the open source community and its cool if this library supports you in building something great! if you need any support in anything else just hit us up!

from react-scrollama.

jsonkao avatar jsonkao commented on June 4, 2024

Thank you, this is really helpful. I will work on allowing text nodes.

from react-scrollama.

JerrySir avatar JerrySir commented on June 4, 2024

Has this problem been solved? How can I solve this problem? Thank’s

from react-scrollama.

jefffriesen avatar jefffriesen commented on June 4, 2024

Adding a related example:

This works:

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

This throws:

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

Uncaught (in promise) TypeError: Cannot read property 'offsetHeight' of null
at Step.updateOffsetHeight

It would be nice to not have to wrap all components inside each Step

from react-scrollama.

jsonkao avatar jsonkao commented on June 4, 2024

The direct child of <Step> must be a DOM element because React Scrollama uses a child's offsetHeight property to calculate the intersection margin. However, only HTMLElements have offsetHeight. That's why using a React component as a direct child of <Step> breaks the library.

For now, to use a custom React component inside <Step>, I recommend wrapping it with a <div> like so:

<Step>
  <div>
    <MyComponent />
  </div>
</Step>

I'm very open to hearing suggestions about how this can be resolved/improved. One solution could be that custom components could forward the ref to their DOM elements. React Scrollama could also check whether a child ref was a DOM element, and use findDOMNode() if it weren't. Both are unideal...

from react-scrollama.

jsonkao avatar jsonkao commented on June 4, 2024

(Note to self: See the wording on the error message Transitions can only be applied to DOM elements, not components from Svelte).

from react-scrollama.

maerzhase avatar maerzhase commented on June 4, 2024

You can use custom components but you have to handle ref forwarding. This is all not specifics to the lib but basics on how react works

https://reactjs.org/docs/forwarding-refs.html#forwarding-refs-to-dom-components

from react-scrollama.

inspectordanno avatar inspectordanno commented on June 4, 2024

@maerzhase But isn't the issue that <Step/> needs a way to accept a ref? The ref needs to be defined in the user code, but then forwarded along to the <Step/> component. This would involve changing the library.

from react-scrollama.

maerzhase avatar maerzhase commented on June 4, 2024

I am not sure what you mean by that. The step component is actually creating a ref for each step, thats why the child either needs to be a html element or a custom component that uses ref forwarding.

If your "MyComponent" would use ref forwarding you wouldn't need to wrap a div around it.

from react-scrollama.

jsonkao avatar jsonkao commented on June 4, 2024

@inspectordanno I'm glad this helped! Sorry that the documentation is a bit scattered. @maerzhase I tried doing this once (I gave up) but I do vaguely remember either (a) needing to change <Step/> or (b) needing to force users to use React.forwardRef (which seems kind of too much to ask).

from react-scrollama.

gjhltn avatar gjhltn commented on June 4, 2024

Sorry to be dim.

What should this look like with ref forwarding?

I'm doing

onst Scene = React.forwardRef(({
	currentStepIndex,
	stepIndex
}, ref) =>
	<Step ref={ref} data={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>)

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 }) => {
	  alert('doesn't fire')
    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) => (
			 <Scene currentStepIndex={currentStepIndex} stepIndex={stepIndex} key={stepIndex} />
        ))}
      </Scrollama>
    </div>
  );
};

But onSteoEnter doesn't fire.

and I get this error

Could not get step with id react-scrollama-0
String: "Could not get step with id react-scrollama-0"

from react-scrollama.

maerzhase avatar maerzhase commented on June 4, 2024

@gswirrl you are using standard HTML elements and therefore you don't need React.forwardRef.
You only need React.forwardRef when you use a custom React component inside the <Step/>-component.

This works without React.forwardRef

<Scrollama>
  <Step>
    <div>
      Step 1
    </div>
  </Step>
  <Step>
    <div>
      Step 2
    </div>
  </Step>
</Scrollama>

This only works with React.forwardRef on FancyDiv

<Scrollama>
  <Step>
    <FancyDiv>
      Step 1
    </FancyDiv>
  </Step>
  <Step>
    <FancyDiv>
      Step 2
    </FancyDiv>
  </Step>
</Scrollama>
const FancyDiv = React.forwardRef((props, ref) => (
  <div ref={ref}>
    {props.children}
  </div>
));

from react-scrollama.

gjhltn avatar gjhltn commented on June 4, 2024

@maerzhase thanks, I tried to simplifiy what I'm trying to do and reduced it to the simplest case - maybe I didn't do a good job of explaining.

What I'd tried to illustrate is that I need the <Step> to be inside another component. I want to use those other component instances as the children of Scrollama. ie in pseudo code


const FancyStep = () =>
    <Step ...>
       {/*some stuff here*/}
    </Step>


<Scrollama>
  <FancyStep />
  <FancyStep />
   <FancyStep />
</Scrollama>

from react-scrollama.

maerzhase avatar maerzhase commented on June 4, 2024

@gswirrl in your example you are dropping all the props that the Scrollama component provides to the Step.

const FancyStep = props => <Step {...props}>{/*some stuff here*/}</Step>

Could you elaborate on "...that I need the <Step> to be inside another component..."? Why do you need it to be in your custom component? I am not aware of a convention that would force you to have it as opposed to the actual library example.

from react-scrollama.

gjhltn avatar gjhltn commented on June 4, 2024

@maerzhase I appreciate your kind reply. Yes I am aware the simplified pseudocode drops the props. I was trying to describe the use case in the simplest possible way. Obviously in practice it is a very great deal more complicated than the pseudo code I posted.

If you nest step in another component it errors. In your example too.

I'm building a higher level abstraction and in a nutshell the steps compose a good bit of additional functionality and get passed around in ways which are easy if they are wrapped in a component and awkward otherwise.

My question though is really simple - is there a way to put a step inside another component which is the child of the scrolama component?

from react-scrollama.

maerzhase avatar maerzhase commented on June 4, 2024

@gswirrl yes this should work as long as you don't drop the props that are provided to the child components of the Scrollama component.

If you still experience problems please provide a reproducable example and no pseudo-code—otherwise I cannot help you with your problem.

For the future we will definitely add more examples that will also include your use-case.

from react-scrollama.

gjhltn avatar gjhltn commented on June 4, 2024

Thanks! I hoped it would work like this too but it doesn't seem to. Adapting the readme example...

import React, {useState} from "react"

import { Scrollama, Step } from 'react-scrollama';
	
const FancyStep = ({
	stepIndex,
	currentStepIndex
}) => <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>

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) => (
	   <FancyStep key={stepIndex} stepIndex={stepIndex} currentStepIndex={currentStepIndex}/>
       ))}
      </Scrollama>
    </div>
  );
};

export default ScrollamaDemo;|

Which as I say, gives this error

Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?

Check the render method of `Scrollama`.
FancyStep
_classCallCheck
div
ScrollamaDemo
_classCallCheck
PureComponent
ReactDevOverlay
_classCallCheck
AppContainer
Root

which is why, in my very first post above, I was trying to forward the reference, it it seems that that too does not in fact work, as while it fixes this error, as I noted originally, it fails again downstream of there.

I hope I'm just doing this wrong, but at the moment i ant find a way at all to have the Step in a nested component 🙁

many many thanks again for your help!

from react-scrollama.

maerzhase avatar maerzhase commented on June 4, 2024

@gswirrl aaaaand in your example code your are still dropping the props. Sorry I didn't know anymore how to explain it to you—So I set up a codesandbox that illustrates what you are trying to achieve:

https://codesandbox.io/s/react-scrollama-custom-step-component-rnr7d?file=/src/App.js

from react-scrollama.

gjhltn avatar gjhltn commented on June 4, 2024

@maerzhase thank you I'm most grateful for your patience and help. Youve actually nailed it here, but a bit differently than we both thought....

The sandbox works excellently, as you say, but when I ran that same code verbatim in my env, it didn't work. Turns out I am on react-scrollama": "2.2.16" and if I change the sandbox to that it errors too in the same way mine was doing.

I think that might be the issue? 😀

However.... that new 2.3 version introduces a new problem. I'm in next.js and ssr is dying because window isn't defined. That should be work roundable however. if it's useful I can open a separate issue for that?

53004E1D-7AB2-42FE-AB6B-05348D2B9612

from react-scrollama.

maerzhase avatar maerzhase commented on June 4, 2024

@gswirrl hmm you are right, i must admit i joined the project rewriting the code-base which is now on the prerelease 2.3.0-beta.0. So i can't vouche for the last releases 😭

About SSR: Scrollama highly depends on window functionality. Currently the easiest fix is to use next-dynamic, but please open an issue so we can maybe try to find a solution to make ssr possible! Cheers!

from react-scrollama.

Related Issues (20)

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.