Comments (22)
@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.
@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.
@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.
Thank you, this is really helpful. I will work on allowing text nodes.
from react-scrollama.
Has this problem been solved? How can I solve this problem? Thank’s
from react-scrollama.
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.
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.
(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.
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.
@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.
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.
@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.
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.
@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.
@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.
@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.
@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.
@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.
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.
@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.
@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?
from react-scrollama.
@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)
- `defaultProps` warning HOT 1
- Call for maintainers HOT 2
- ReferenceError: regeneratorRuntime is not defined HOT 4
- Progress argument is not returning percent of completion HOT 9
- onStepEnter isn't being called in gatsby HOT 20
- Step height changes mess up progress intersection
- Resizing should be more exposed to the user HOT 1
- Probably shouldn't overwrite the `id` on Step's child
- Rewrite using functional components and hooks HOT 3
- Jest Snapshots HOT 7
- Update from 2.2.10 to 2.2.12 throws TypeError: Failed to construct 'IntersectionObserver': The provided double value is non-finite. HOT 1
- "window" is not available during server side rendering HOT 4
- 2.0.3-beta breaks next.js (throws error under ssr, no workaround) HOT 1
- Update peerDependencies - allow React 17 and 18 HOT 3
- Failed to construct 'IntersectionObserver' HOT 2
- Gatsby SSR Issue
- Forgot default Props for offset in Scrollama.js HOT 1
- Background image resolution changes
- Providing Types for TypeScript? HOT 5
- Scroll exits at a specific webpage height
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from react-scrollama.