React Native SectionList scroll to section - javascript

I just changed my ListView to React Native's new SectionList and now the app crashes when I attempt to use the scrollTo function, stating that it's undefined. I tried looking up new/alternative functions that may help, but none of them seem to be working.
What's the proper protocol for programmatically scrolling to a specific section with the new SectionList?
Links I've been consulting thus far:
https://github.com/facebook/react-native/issues/13151
https://facebook.github.io/react-native/releases/0.43/docs/virtualizedlist.html#scrolltoend
My current attempt:
var params = {animated:true,offset:Platform.OS == "ios" ? 244 : 264}
_mainListView.scrollToOffset(params)

<SectionList
ref={(sectionList) => { this.sectionList = sectionList }} .../>
this.sectionList.scrollToLocation(
{
sectionIndex: sectionIndex,
itemIndex: itemIndex
}
);
This is what I used to get it working using a mix of this post and https://snack.expo.io/HJp9mEQkG

This is how I scroll to end
listRef.current?.scrollToLocation({
animated: true,
sectionIndex: sections.length - 1,
itemIndex: sections[sections.length - 1].data.length - 1,
})
This is how I scroll to top
listRef.current?.scrollToLocation({
animated: true,
sectionIndex: 0,
itemIndex: 0,
})

scrollToSection = (sectionIndex,itemIndex = 1 ) => {
this.refs.foo.scrollToLocation({
sectionIndex: sectionIndex,
itemIndex: itemIndex
});
}
sectionList:
<SectionList
ref = "foo",
//something
/>

For me workaround is
list.current?.getScrollResponder()?.scrollTo({ x: 0, y: 0, animated: false })

Related

use gsap scrollTrigger in react

I am trying to imply some animations in an image while scrolling , the image will grow while scrolling down and return to normal when scrolling up . The reference : codepen.
This is my react code :
<ArticleWrapper ref={ref}>
<img id='grow' className='image' src={Img} alt='Image' />
</ArticleWrapper>
I have tried to implement this but it didnt work when I scroll :
const ref = useRef(null);
useEffect(() => {
const element = ref.current;
scrollTrigger: {
trigger: "#grow",
scrub: 1.5,
start: "top center",
end: "+=400",
ease: "power1.out"
},
{
duration: 1,
scale: 1
}
);
}, []);
Any idea how to do that ?

How to use useSprings?

I'm trying to create an animated text char by char to bounce from right to left, but I need to add a different delay to each char.
So far the animation looks nice the problem is that the delay is not updating for each char.
This is my code:
import React from "react";
import { useSprings, animated } from "react-spring"
import s from '../../styles/pages/home.module.scss'
// HERE CREATE AN ARRAY CHAR BY CHAR INCLUDING " ", FROM A STRING
let textString = "Random text for this example."
let textArray = Array.from(textString)
const HeroText = () => {
const springs = useSprings(
textArray.length,
textArray.map((item, i)=> ({
id : i,
from : {opacity: 0, translateX : '1000px'},
to: {opacity: 1, translateX : '0px'},
delay: (0.5 + i / 10),
config: { mass: 4, tension: 200, friction: 30}
}))
)
let elements = springs.map((spring, i) => {
console.log(spring)
return(
<animated.span key={i} style={{...spring}}>
{textArray[i] === ' ' ? <span> </span> : textArray[i]}
</animated.span>
)
})
return(
<div className={s.heroText}>
<h1 className={"my-heading divided-heading"}>
{elements}
</h1>
</div>
)
}
export default HeroText
On the console.log(spring), I can actually see that all the objects have different "delay" values, but on render they all animate at the same time, so it does not look like the text is animated char by char.
I have read the react-spring documentation but I did not find it to be very helpful, so if someone can help me understand what I'm missing I would be glad.
Thanks!
so after allot of research I found out that the best way to do what I was trying to do was to use "useTransition".
This was the final code, working properly.
import React from "react";
import { animated, useTransition } from "react-spring"
import s from '../../styles/pages/home.module.scss'
// HERE CREATE AN ARRAY CHAR BY CHAR INCLUDING " ", FROM A STRING
let textString = "Hi, I'm Stephane Ribeiro. Want to como on a full stack journey trough my mind?!"
let textArray = Array.from(textString)
let objArray = textArray.map((item, i) => {
return ({
char : item,
key: i
})
})
const HeroText = () => {
const tranConfig = {
from : {opacity: 0, translateX : '1000px'},
enter: {opacity: 1, translateX : '0px'},
config: { mass: 4, tension: 200, friction: 30},
trail: 50
}
const transition = useTransition(objArray, tranConfig)
let elements = transition((values, item) => {
return(
<animated.span key={item.key} style={values}>
{item.char === ' ' ? <span> </span> : item.char}
</animated.span>
)
})
return(
<div className={s.heroText}>
<h1 className={"my-heading divided-heading"}>
{firstElements}
</h1>
</div>
)
}
export default HeroText
How did you apply different delay time for each char. I have seen your last code there is no different delay time

Framer Motion opacity keyframe only animates on initial render

I'm using Framer Motion
The box should go from opacity: 0 to 1 and increase in height on every state toggle. However, the height is different based on the condition.
I don't have a clue why "height" is being animated every time - correctly, but "opacity" is only animated in the first render.
I tried [0, 1, 0] & [1, 0, 1] too, but none of them has the desired effect.
I even tried [0, 1, 0.5] to test better, but it stays at 0.5.
Code
https://codesandbox.io/s/angry-raman-bc9sf?file=/src/App.js
import { motion } from "framer-motion";
import { useState } from "react";
export default function App({ href = "#", label, icon, notifCount }) {
const [conditionIsMet, setConditionIsMet] = useState(false);
const notifVariants = {
conditionA: {
opacity: [0, 1],
height: ["40px", "90px"]
},
conditionB: {
opacity: [0, 1],
height: ["40px", "200px"]
}
};
return (
<>
{`Condition is ${conditionIsMet ? "A" : "B"}`}
<button onClick={() => setConditionIsMet(!conditionIsMet)} />
<motion.span
animate={conditionIsMet ? "conditionA" : "conditionB"}
variants={notifVariants}
/>
</>
);
}
I think it's a bug but as a temporary fix you can use opacity: [0, 1.01] for conditionB.
please open an issue for this bug.

How execute this two OnScrolls?

I'm following this tutorial https://medium.com/appandflow/react-native-collapsible-navbar-e51a049b560a to create a navbar collapsed. Work's fine, but there's a problem, in this tutorial the autor set the props onscroll of the FlatList:
onScroll={Animated.event( [{ nativeEvent: { contentOffset: { y: this.state.scrollAnim } } }], { useNativeDriver: true },)}
But i already using this onScroll Props for:
onScroll={event => this.handleScroll(event)}
My handle scroll will verify if is the end of the scroll and load more feed:
handleScroll (event) {
var endOfPage = event.nativeEvent.layoutMeasurement.height + event.nativeEvent.contentOffset.y >=
event.nativeEvent.contentSize.height;
if (endOfPage) {
this.getSections()
}
}
I cant running my function and the autor command in the same time. Is there a way to execute this two OnScroll?
My componenet AnimatedFlatList (The first OnScroll will not work because the other will override the last):
<AnimatedFlatList
contentContainerStyle={[collapse.contentContainer, {paddingTop: this.props.navigation.state.params.category == '' ? 166.5 : 96.5}]}
onMomentumScrollBegin={this._onMomentumScrollBegin}
onMomentumScrollEnd={this._onMomentumScrollEnd}
onScroll={event => this.handleScroll(event)}
onScrollEndDrag={this._onScrollEndDrag}
data={this.state.sections}
renderItem={this._renderSectionItem}
extraData={this.state}
keyExtractor={(item, index) => index.toString()}
removeClippedSubviews
onScroll={Animated.event( [{ nativeEvent: { contentOffset: { y: this.state.scrollAnim } } }], { useNativeDriver: true },)}
/>
Based off of this answer:
onScroll={Animated.event(
[{ nativeEvent: { contentOffset: { y: this.state.scrollAnim } } }],
{
useNativeDriver: true,
listener: event => this.handleScroll(event)
});
}}

How to use React TransitionMotion willEnter()

Using React Motion's TransitionMotion, I want to animate 1 or more boxes in and out. When a box enters the view, it's width and height should go from 0 pixels to 200 pixels and it's opacity should go from 0 to 1. When the box leaves the view, the reverse should happen (width/height = 0, opacity = 0)
I have tried to solve this problem here http://codepen.io/danijel/pen/RaboxO but my code is unable to transition the box in correctly. The box's style jumps immediately to a width/height of 200 pixels instead of transitioning in.
What is wrong with the code?
let Motion = ReactMotion.Motion
let TransitionMotion = ReactMotion.TransitionMotion
let spring = ReactMotion.spring
let presets = ReactMotion.presets
const Demo = React.createClass({
getInitialState() {
return {
items: []
}
},
componentDidMount() {
let ctr = 0
setInterval(() => {
ctr++
console.log(ctr)
if (ctr % 2 == 0) {
this.setState({
items: [{key: 'b', width: 200, height: 200, opacity: 1}], // fade box in
});
} else {
this.setState({
items: [], // fade box out
});
}
}, 1000)
},
willLeave() {
// triggered when c's gone. Keeping c until its width/height reach 0.
return {width: spring(0), height: spring(0), opacity: spring(0)};
},
willEnter() {
return {width: 0, height: 0, opacity: 1};
},
render() {
return (
<TransitionMotion
willEnter={this.willEnter}
willLeave={this.willLeave}
defaultStyles={this.state.items.map(item => ({
key: item.key,
style: {
width: 0,
height: 0,
opacity: 0
},
}))}
styles={this.state.items.map(item => ({
key: item.key,
style: {
width: item.width,
height: item.height,
opacity: item.opacity
},
}))}
>
{interpolatedStyles =>
<div>
{interpolatedStyles.map(config => {
return <div key={config.key} style={{...config.style, backgroundColor: 'yellow'}}>
<div className="label">{config.style.width}</div>
</div>
})}
</div>
}
</TransitionMotion>
);
},
});
ReactDOM.render(<Demo />, document.getElementById('app'));
As per the documentation of styles under the TransitionMotion section (and I don't claim to have understood all of it entirely :)):
styles: ... an array of TransitionStyle ...
The key thing to note here is that there are 2 types of style objects that this library deals with (or at least this TransitionMotion part of it) and it calls them TransitionStyle and TransitionPlainStyle.
The previous values passed into styles attribute were of TransitionPlainStyle. Changing them to TransitionStyle magically starts animating the Enter sequence.
You can read more about 2 different types mentioned above over here.
styles={this.state.items.map(item => ({
key: item.key,
style: {
width: spring(item.width),
height: spring(item.height),
opacity: spring(item.opacity)
}
}))}
Forked codepen demo.
Again, I do not fully understand the inner workings of it just yet. I just know that your styles had to be changed in the above way to make it work.
I will be happy if someone can educate me on this as well.
Hope this helps.

Categories

Resources