react native layoutanimation config easeInout not working (IOS) - react-native

i have a room list, when any room have new message, I sorted this room to top then re-render the flatList with LayoutAnimation(testing from IOS simulator):
const CONFIG = {
duration: 300,
create: {
type: LayoutAnimation.Types.linear,
property: LayoutAnimation.Properties.opacity
},
update: {
type: LayoutAnimation.Types.easeInEaseOut
},
delete: {
type: LayoutAnimation.Types.easeInEaseOut,
property: LayoutAnimation.Properties.opacity
}
}
export function animate () {
LayoutAnimation.configureNext(CONFIG)
}
but when data changed, i didnt see any animation without fade, as video below:
video
Updated video with transition:
this is updated answer with transition
other information:
"react": "17.0.2",
"react-native": "^0.68.0",
"react-native-gesture-handler": "^2.5.0",
"react-native-reanimated": "^2.9.1",

To Archive that you can use Animated in React Native, you can check this article that explains how to do it step by step from here
And you can achieve that with FlatList by using Transitioning View from react-native-reanimated like this example:
import React, { useState, useEffect, useRef } from 'react';
import {
Text,
View,
TouchableOpacity,
StyleSheet,
FlatList,
} from 'react-native';
import { datas, sortRoom, currentUser } from './components/datas';
import { RoomItem } from './RoomItem';
import { Transition, Transitioning } from 'react-native-reanimated';
const transition = (
<Transition.Together>
<Transition.Change durationMs={500} />
</Transition.Together>
);
const styles = StyleSheet.create({
item: {
width: '100%',
height: 100,
backgroundColor: 'red',
marginVertical: 10,
justifyContent: 'center',
alignItems: 'center',
},
itemText: {
fontSize: 21,
color: '#fff',
},
});
export default function App() {
const [roomList, setRoomList] = useState(datas);
const parentRef = useRef();
return (
<React.Fragment>
<TouchableOpacity
onPress={() => {
//get random room and append to top by assign SendDate to now
parentRef.current.animateNextTransition()
const newRooms = [...roomList];
const randomIndex = Math.floor(Math.random() * roomList.length);
const matchedNewRoom = [...roomList][randomIndex];
matchedNewRoom.LastMsg.SendDate = new Date().getTime();
const sortedRoom = sortRoom(newRooms);
setRoomList(sortedRoom);
}}
style={{
marginTop: 20,
justifyContent: 'center',
alignItems: 'center',
padding: 5,
}}>
<Text style={{ color: 'blue' }}> Re-Order </Text>
</TouchableOpacity>
<Transitioning.View ref={parentRef} transition={transition}>
<FlatList
style={{
width: '100%',
}}
data={roomList}
keyExtractor={(item) => item.RoomName.toString()}
renderItem={({item}) => <RoomItem room={item} currentUser={currentUser}/>}
contentContainerStyle={{
flexGrow: 1,
}}
initialNumToRender={20}
onEndReachedThreshold={0.1}
/>
</Transitioning.View>
</React.Fragment>
);
}
You can check the demo here.

Related

Change component style when state is set to certain value

I have a counter that counts down, when the counter hits zero, I would like a style to change. The counter displays properly but the style never changes. How can I get the style to change when the counter hits a certain value?
Below is the code for a very basic example.
import React, { useState, useEffect } from "react";
import { Text, StyleSheet, SafeAreaView, TouchableOpacity, View } from "react-native";
const ActionScreen = () => {
const [timeLeft, setTimeLeft] = useState(4);
const [opac, setOpac] = useState(0.8);
useEffect(() => {
const interval = setInterval(() => setTimeLeft(timeLeft - 1), 1000);
if (timeLeft > 2) {
setOpac(0.8);
console.log("GT");
} else {
setOpac(0.5);
console.log("LT");
}
console.log("opac: ", opac);
if (timeLeft === 0) {
// clearInterval(interval);
setTimeLeft(4);
// setOpac(0.5);
}
return () => {
clearInterval(interval);
};
}, [timeLeft]);
return (
<SafeAreaView style={styles.container}>
<View style={styles.subActionContainer}>
<TouchableOpacity
style={[
styles.topButtons,
{
opacity: opac,
}
]}
>
<Text
style={styles.buttonText}>
{timeLeft}
</Text>
</TouchableOpacity>
</View>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: 25,
backgroundColor: 'black',
},
subActionContainer: {
flexDirection: "row",
alignContent: 'space-between',
},
topButtons: {
flex: 1,
backgroundColor: 'orange',
},
buttonText: {
fontSize: 18,
textAlign: 'center',
padding: 10,
color: 'white',
},
buttonFail: {
borderWidth: 1,
marginHorizontal: 5,
}
});
export default ActionScreen;
I'm fairly new to React-Native but read somewhere that some styles are set when the app loads and thus don't change but I have also implemented a Dark Mode on my app that sets inline styling, which works well. Why isn't the styling above changing?
Thank you.
you can create your timer and create a method isTimeOut and when it is true you can change the background
import * as React from 'react';
import { Text, View, StyleSheet } from 'react-native';
import {useTimerCountDown} from './useCountDownTimer'
export default function App() {
const {minutes, seconds, setSeconds} = useTimerCountDown(0, 10);
const isTimeOut = Boolean(minutes === 0 && seconds === 0);
const handleRestartTimer = () => setSeconds(10);
return (
<View style={styles.container}>
<View style={[styles.welcomeContainer,isTimeOut &&
styles.timeOutStyle]}>
<Text>welcome</Text>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: 10,
backgroundColor: '#ecf0f1',
padding: 8,
},
welcomeContainer:{
backgroundColor:'red',
},
timeOutStyle:{
backgroundColor:'blue',
}
});
See the useTimerCountDown hook here in this
working example

Why is React Native FlatList not working on Android but it is for Web?

I am using Expo to build a react native app with AWS for the backend.
I am trying to display a list of friends using FlatList and the AWS data. The list works and is visible on my web browser, but for some reason, it is not displaying on my Android phone. What might the issue be?
FriendsList.tsx
import { API, graphqlOperation } from 'aws-amplify';
import * as React from 'react';
import {useEffect, useState} from 'react';
import { FlatList, View, ScrollView, Text, StyleSheet } from 'react-native';
import { listUsers } from '../graphql/queries';
import FriendsListItem from '../components/FriendsListItem';
export default function FriendsList() {
const [ users, setUsers ] = useState([]);
useEffect( () => {
const fetchUsers = async () => {
try {
const usersData = await API.graphql(
graphqlOperation(
listUsers
)
)
setUsers(usersData.data.listUsers.items);
} catch (e) {
}
}
fetchUsers();
},[])
return (
<View style={ styles.container }>
<FlatList
style={{ width: '100%' }}
data={users}
renderItem={({ item }) => <FriendsListItem user={item} />}
keyExtractor={(item) => item.id}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
});
FriendsListItem.tsx
import * as React from 'react';
import { View, Text, StyleSheet, Image, TouchableWithoutFeedback } from 'react-native';
import { API, graphqlOperation, Auth } from "aws-amplify";
import { User } from './types';
export type FriendsListItemProps = {
user: User;
}
const FriendsListItem = ( props: FriendsListItemProps ) => {
const { user } = props;
return (
<TouchableWithoutFeedback>
<View style={styles.container}>
<View style={styles.lefContainer}>
<Image source={{ uri: user.imageUri }} style={styles.avatar}/>
<View style={styles.midContainer}>
<Text style={styles.username}>{user.name}</Text>
<Text numberOfLines={2} style={styles.status}>{user.email}</Text>
</View>
</View>
</View>
</TouchableWithoutFeedback>
);
}
export default FriendsListItem;
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
width: "100%",
justifyContent: 'space-between',
//height: '100%',
},
lefContainer: {
flexDirection: 'row',
padding: 16,
},
midContainer: {
justifyContent: 'space-around'
},
avatar: {
width: 60,
height: 60,
borderRadius: 50,
marginRight: 15,
},
username: {
fontWeight: 'bold',
fontSize: 16,
},
status: {
fontSize: 16,
color: 'grey',
},
});
Looking at the code example, in your FriendsListItem component, any time you use your "user" prop, you need to change it. For example, change this:
user.imageUri
to this:
user.item.imageUri
What you are passing in is an object (e.g. user), which then contains another object (e.g. item), which finally contains your data (e.g. imageUri).
I figured it out. Turns out I am just an idiot. The expo app on my phone was logged into a different account so that's why it wasn't showing any friends for that user.

FlatList not rendering row

I am trying to learn FlatList component of react-native. Observing a tutorial, I have implemented a sample applications which list components inside a scrollview. I am trying to replace scrollview with FlatList, but items are not renderings on the screen. I have included the main source code here.
App.js
import React, { Component } from 'react'
import {
StyleSheet,
View,
ScrollView,
FlatList
} from 'react-native'
import ColorButton from './components/ColorButton'
class App extends Component {
constructor() {
super()
this.state = {
backgroundColor: 'blue'
}
this.changeColor = this.changeColor.bind(this)
}
changeColor(backgroundColor) {
this.setState({backgroundColor})
}
render() {
const { backgroundColor } = this.state
return(
<FlatList
data = {'red', 'green', 'salmon'}
renderItem = {(color) => {
<ColorButton backgroundColor={color} onSelect={this.changeColor}></ColorButton>
} } />
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: 20
}
})
export default App
ColorButton.js
import React from 'react'
import {
StyleSheet,
Text,
View,
TouchableHighlight
} from 'react-native'
const ColorButton = ({ backgroundColor, onSelect=f=>f }) => (
<TouchableHighlight
style = {styles.button}
onPress={() => onSelect(backgroundColor)}
underlayColor="orange">
<View style = {styles.row}>
<View style = {[styles.sample, {backgroundColor}]} />
<Text style = {styles.text}>backgroundColor</Text>
</View>
</TouchableHighlight>
)
const styles = StyleSheet.create({
button: {
margin: 10,
padding: 10,
borderWidth: 2,
borderRadius: 10,
alignSelf: 'stretch',
backgroundColor: 'rgba(255,255,255,0.8)'
},
row: {
flexDirection: 'row',
alignItems: 'center'
},
sample: {
height: 20,
width: 20,
borderRadius: 10,
margin: 5,
backgroundColor: 'white'
},
text: {
fontSize: 30,
margin: 5
}
})
export default ColorButton
Change your code for flatlist to the one below :
<FlatList
data = {['red', 'green', 'salmon']}
renderItem = {({item}) => {
<ColorButton backgroundColor={item} onSelect={this.changeColor}>
</ColorButton>
} } />
Hope it helps. feel free for doubts

React native SectionList not updating

I am developing a sample app as part of learning react-native, in which it has a ColorForm that accepts the value from a TextInput and with the help of Props, the data will be sent to the Main view, such as App. The App has a SectionList that doesn't update with the new value inputs from ColorForm.
Following is the source code that I have used:
App.js
import React, { Component } from 'react'
import {
StyleSheet,
SectionList,
Text,
Alert
} from 'react-native'
import ColorButton from './components/ColorButton'
import ColorForm from './components/ColorForm'
class App extends Component {
constructor() {
super()
this.state = {
backgroundColor: 'blue',
availableColors: ['red', 'green', 'yellow', 'pink']
}
this.changeColor = this.changeColor.bind(this)
this.newColor = this.newColor.bind(this)
}
changeColor(backgroundColor) {
this.setState({ backgroundColor })
}
newColor(color) {
const colors = [
...this.state.availableColors,
color
]
this.setState(colors)
}
render() {
const { backgroundColor, availableColors } = this.state
return (
<SectionList style={styles.list}
backgroundColor={backgroundColor}
sections={[{ title: "Header", data: availableColors }]}
renderSectionHeader={({ section }) => (
<ColorForm onNewColor={this.newColor} />
)}
renderItem={({ item }) => (
<ColorButton backgroundColor={item} onSelect={this.changeColor} />
)}
keyExtractor={(item, index) => index}
/>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: 20
},
list: {
marginTop: 40
}
})
export default App
ColorForm.js
import React, { Component } from 'react'
import {
View,
Text,
StyleSheet,
TextInput
} from 'react-native'
import PropTypes from 'prop-types'
export default class ColorForm extends Component {
constructor() {
super()
this.state = {
txtColor: ''
}
this.submit = this.submit.bind(this)
}
submit() {
this.props.onNewColor(this.state.txtColor.toLowerCase())
this.setState({ txtColor: '' })
}
render() {
return (
<View style={styles.container}>
<TextInput
style={styles.txtInput}
placeholder="Enter a color..."
onChangeText={(txtColor) => this.setState({ txtColor })}
value={this.state.txtColor}
/>
<Text style={styles.button} onPress={this.submit}>Add</Text>
</View>
)
}
}
ColorForm.propTypes = {
onNewColor: PropTypes.func.isRequired
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row',
justifyContent: 'space-around',
backgroundColor: 'lightgrey',
height: 70,
paddingTop: 20
},
txtInput: {
flex: 1,
margin: 5,
padding: 5,
borderWidth: 2,
fontSize: 20,
borderRadius: 5,
backgroundColor: 'snow'
},
button: {
backgroundColor: 'darkblue',
margin: 5,
padding: 5,
alignItems: 'center',
justifyContent: 'center',
color: 'white',
fontSize: 20
}
})
Can anyone help me to sort out the issue? Thanks in advance.
It looks like the state is not being updated in your method newColor, since availableColors is an array u can use push operation to add new value to the array update the code as below and it will work.
newColor(color) {
console.log('adding', color)
const colors = this.state.availableColors
colors.push(color)
this.setState(colors)
}

Using react-spring for react-native

I want to use this library for react-native but couldn't figure out how. The documentation link for react-native is broken. Can i use the library for react-native?
React-Spring can be used for react-native. They have updated it for all platform.
Try this out:-
yarn add react-spring#5.3.0-beta.0
import React from 'react'
import { StyleSheet, Text, View, TouchableWithoutFeedback } from 'react-native'
import { Spring, animated } from 'react-spring/dist/react-spring-native.esm'
const styles = {
flex: 1,
margin: 0,
borderRadius: 35,
backgroundColor: 'red',
alignItems: 'center',
justifyContent: 'center',
}
export default class App extends React.Component {
state = { flag: true }
toggle = () => this.setState(state => ({ flag: !state.flag }))
render() {
const { flag } = this.state
return (
<Spring native from={{ margin: 0 }} to={{ margin: flag ? 100 : 0 }}>
{props => (
<TouchableWithoutFeedback onPressIn={this.toggle}>
<animated.View style={{ ...styles, ...props }}>
<Text>It's working!</Text>
</animated.View>
</TouchableWithoutFeedback>
)}
</Spring>
)
}
}
`
For anyone with issues, try using a different import. This worked for me on expo's react native.
import React, { Component } from 'react';
import { Text, View, TouchableWithoutFeedback } from 'react-native';
import { Spring, animated } from 'react-spring/renderprops-native';
const AnimatedView = animated(View);
const styles = {
flex: 1,
margin: 0,
backgroundColor: 'red',
alignItems: 'center',
justifyContent: 'center',
}
export default class App extends Component {
state = { flag: true }
toggle = () => this.setState(state => ({ flag: !state.flag }))
render() {
const { flag } = this.state
return (
<Spring
native
from={{ margin: 0 }}
to={{ margin: flag ? 100 : 0 }}
>
{props => (
<TouchableWithoutFeedback onPressIn={() => this.toggle()}>
<AnimatedView style={{ ...styles, ...props }}>
<Text>{flag ? "true" : 'false'}</Text>
</AnimatedView>
</TouchableWithoutFeedback>
)}
</Spring>
);
}
}
The example below works.
import React, {Component} from 'react';
import {Platform, StyleSheet, Text, View, TouchableWithoutFeedback} from 'react-native';
import { Spring, animated } from 'react-spring'
const AnimatedView = animated(View)
const styles = {
flex: 1,
margin: 0,
borderRadius: 35,
backgroundColor: 'red',
alignItems: 'center',
justifyContent: 'center',
}
type Props = {};
export default class App extends Component<Props> {
state = { flag: true }
toggle = () => this.setState(state => ({ flag: !state.flag }))
render() {
const { flag } = this.state
return (
<Spring native from={{ margin: 0 }} to={{ margin: flag ? 100 : 0 }}>
{props => (
<TouchableWithoutFeedback onPressIn={this.toggle}>
<AnimatedView style={{ ...styles, ...props }}>
<Text>It's working!</Text>
</AnimatedView>
</TouchableWithoutFeedback>
)}
</Spring>
);
}
}