How to use refreshControl on a ScrollView but prevent dragging direction? - react-native

I have content that I want to "refresh" with a RefreshControl but I do not want the content to scroll upwards. I was originally under the impression that setting bounces=false and scrollEnabled=true would achieve this.

How about you set a key to the Component, then update it when you want to refresh it.
When a key changes, React see it as a new component. As a result, it will literally refresh the component.
export default () => {
const [refreshKey, setRefreshKey] = React.useState('randomstring');
// call me when refresh required
const refresh = () => {
setRefreshKey(refreshKey + 'randomstring');
};
return (
<ScrollView key={refreshKey}>
{/* Some Awesome Contents */}
</ScrollView>
);
};

Related

Nested ScrollView block parent scroll when started scrolling in child

I have a React Native app with a parent ScrollView component that wraps other 2 ScrollViews that are siblings. How could I force the parent to only scroll when I've started scrolling from outside the child components?
Current behavior:
When I start scrolling in a child, the child scrolls, but when the list reaches the end, the parent starts scrolling (finger was not removed from the screen, so it was the same scrolling action).
Desired behavior:
When I start scrolling in a child, the child scrolls, but when the list reaches the end, the parent does NOT scroll until I interrupt the current scrolling action and start scrolling again from the area of the parent.
You can't have nested scroll views in the same direction. You can try to improve the UI.
Even for the user this can be confusing.
Send a screenshot, so people can better understand what the goal is.
export const ScrollEnabledContext = createContext(null);
const Parent = () => {
const ref = useRef(null);
const setIsEnabled = (bool) => {
ref.current?.setNativeProps({ scrollEnabled: bool });
};
return (
<ScrollEnabledContext.Provider value={setIsEnabled}>
<ScrollView ref={ref} nestedScrollEnabled={true}>
<ChildScrollView />
</ScrollView>
</ScrollEnabledContext.Provider>
);
};
const ChildScrollView = () => {
const value = useContext(ScrollEnabledContext);
return (
<ScrollView onTouchStart={() => value(false)} onTouchEnd={() => value(true)}>
....
</ScrollView>
);
};

Change SVG component on press with React Native

Background
Pretty simple question: I want to create a "like" button in RN. To do this I have to separate components which are SVG files. One is just the outline of a heart, the other one is filled.
The screen in which I'm trying to build this button is a Function component so I should use hooks. I know about state but don't know how to properly use it.
What I need
A Touchable Opacity component which holds an onPress method which changes the image component when pressed.
Thanks a lot in advance!
import React ,{useState} from 'react';
import {TouchableOpacity } from "react-native";
export default function Like() {
const [isLiked,setIsLiked]=useState(false) ;
const handleLikePress=()=>{
setIsLiked(!isLiked)
}
return (
<TouchableOpacity onPress={handleLikePress}>
{isLiked? <FilledHeartSVG/>: <OutlineHeartSVG/> }
</TouchableOpacity>
)
}
by default, we are showing an outline of a heart SVG
when press event trigger we are changing isLiked state value
if isLiked is true then show filled heart SVG
if isLiked is false then show outline of a heart SVG
FilledHeartSVG and OutlineHeartSVG is just example use your SVG there
You can do something like below, here i have made a toggle for the text but you can change it to your image component, also the callback prop can be used if you want to use that outside the LikeButton
const LikeButton = ({callback}) => {
const [liked, setLiked] = React.useState(false);
return (
<TouchableOpacity onPress={()=>{
setLiked(!liked);
if(callback)
{
callback();
}
}}>
<Text>{liked?"Liked":"Like"}</Text>
</TouchableOpacity>
);
};
You can tryout this snack which uses icons
https://snack.expo.io/#guruparan/likebutton

Get current scroll position of FlatList

I have this code:
<FlatList
ref={(x) => (this.flatList = x)}
data={players}
style={this.props.style}
/>
What I need is to save the current scroll position of the FlatList when the user e.g. navigates away.
So something like this.flatList.getCurrentScrollPosition().
Is there such a thing?
FlatList inherits all of ScrollView props. Therefore you can use onScroll.
onScroll = (event) => {
const scrollOffset = event.nativeEvent.contentOffset.y
}

Changing Drawer left and right button image dynamically?

react-native-router-flux v3.37.0
react-native v0.42.0
I'm trying to update drawer navigation bar right image dynamically where I have used leftButtonImage, rightButtonImage, where once user read all the notification I want to change the button image.
I could not manage to re-render or update this button image, Is this feature not supported or is there something that I'm missing?
You can call Actions.refresh when you need to refresh the view, example:
Actions.refresh({key: 'profileView', renderRightButton: this.renderRightButton });
and also define renderRightButton:
renderRightButton() {
return (
<TouchableOpacity onPress={ console.log(this) } >
<Text>Logout</Text>
</TouchableOpacity>
)
}
and lastly don't forget to import Actions from react-native-router-flux
import {Actions} from 'react-native-router-flux';
You can re-render using props or states naturally.
Check the states you want, and apply image resource following the states.(or props)
let NotiImage = {
normal: require('../assets/image/notinormal.png');
new: require('../assets/image/new.png');
}
render() {
...
<Image source={ this.state.newNoti ? NotiImage.new : NotiImage.normal } />
...
}

React Native/Shoutem: navigateBack() not working

My Problem is that I would like to navigateBack() from the BountyDetailsScreen to the LoyaltyScreen, but the navigateBack() function call does not trigger any action. When I log the function it says:
The only thing I notice is, that the navigationStack is empty. When I do the same with the navigateTo function it is working, but then I have a messed up navigation stack.
In my LoyaltyScreen.js I am displaying a ListView. It is a RN ListView (not imported from shoutem).
LoyaltyScreen.js
renderRow(bounty) {
return (
<ListBountiesView
key={bounty.id}
bounty={bounty}
onDetailPress={this.openDetailsScreen}
redeemBounty={this.redeemBounty}
/>
);
}
ListBountiesView.js
The ListBountiesView renders each ListView Row and opens a Detail Screen when clicked on the Row.
render() {
const { bounty } = this.props;
return (
<TouchableOpacity onPress={this.onDetailPress}>
{bounty.type == 0 ? this.renderInShopBounty() : this.renderContestBounty()}
<Divider styleName="line" />
</TouchableOpacity>
);
}
BountyDetailsScreen.js
In the BountyDetailsScreen I display detailed information and would like to navigateBack() to the Loyalty Screen when I press a button.
<Button styleName="full-width" onPress={() => this.onRedeemClick()}>
<Icon name="add-to-cart" />
<Text>Einlösen</Text>
</Button>
onRedeemClick() {
const { bounty, onRedeemPress } = this.props;
onRedeemPress(bounty);
navigateBack();
}
navigateBack is an action creator. You need to map it to props and read it from props in your redeemClick function. Just executing the imported action creator won't do anything since it's not connected to Redux.
Here's an example of you map it to props:
export default connect(mapStateToProps, { navigateBack })(SomeScreen));
Here's how you use it:
const { navigateBack } = this.props;
navigateBack();
I can see that airmiha's answer is what you're looking for, but I just wanted to add onto it.
You can also use hasHistory to set up your #shoutem/ui NavigationBar (if you're using it) with a simple back button that utilises navigateBack().
<NavigationBar
styleName="no-border"
hasHistory
title="The Orange Tabbies"
share={{
link: 'http://the-orange-tabbies.org',
text: 'I was underwhelmed by The Orange Tabbies, but then I looked at that
sweet, sweet back button on the Nav Bar.
#MakeNavBarsGreatAgain',
title: 'Nevermind the cats, check the Nav Bar!',
}}
/>
You can find more examples with the NavigationBar component here.