Loading Indicator while loading item - react-native

I am making react native expo app. And i have page where articles from database are displayed. When i click to button of article i go to page with article. When i click button i am sending all data of article to another screen. I want to load ActivityIndicator while data is displaying.
Help me please
Code:
class HomeScreen extends React.Component {
const { navigate } = this.props.navigation;
return (
<SafeAreaView style={styles.MainContainer}>
<ScrollView
>
<ListView
dataSource={this.state.dataSource}
renderSeparator={this.ListViewItemSeparator}
renderRow={rowData => (
<>
<TouchableOpacity style={{flex:2}}
activeOpacity={.7}
onPress={() => navigate('Articles', {
otherParam: rowData.article_title,
mobile_image: rowData.mobile_image,
article_category: rowData.article_category,
views: rowData.views,
article_content: rowData.article_content
})}>
<Image
source = {{ uri: rowData.mobile_image }}
style={{resizeMode:'cover',width:null,height:null, flex:1, borderRadius:4,
borderWidth:1,
borderColor:'#dddddd'}}
/>
<Text
style={styles.textOfArticle}
>
{rowData.article_title}
</Text>
</TouchableOpacity>
</>
)}
/>
</ScrollView
>
</SafeAreaView>
);
}
}
class ArticleScreen extends React.Component {
static navigationOptions = ({ navigation, navigationOptions }) => {
const { params } = navigation.state;
return {
title: params ? params.otherParam : '',
};
};
state = { animating: true }
componentDidMount = () => {
const { params } = this.props.navigation.state;
const article_title = params ? params.otherParam : '';
const mobile_image = params ? params.mobile_image : '';
const article_category = params ? params.article_category : '';
const views = params ? params.views : '';
const article_content = params ? params.article_content : '';
this.closeActivityIndicator()
}
render() {
const animating = this.state.animating
return (
<View style = {styles.container}>
<ActivityIndicator
animating = {animating}
color = '#bc2b78'
size = "large"
style = {styles.activityIndicator}/>
</View>
)
return (
<SafeAreaView>
<ScrollView>
<Text>{article_title}</Text>
</ScrollView>
</SafeAreaView>
);
}
}

Add a boolean value for activityIndicator, which will used to show or hide activityIndicator.
state = {
showIndicator: true,
}
closeActivityIndicator = () => {
this.setState({ showIndicator: false });
}
In your render use conditional rendering based on showIndicator value
render() {
const animating = this.state.animating;
return (
<SafeAreaView>
{this.state.showIndicator ? (
<View style={styles.container}>
<ActivityIndicator
animating={animating}
color="#bc2b78"
size="large"
style={styles.activityIndicator}
/>
</View>
) : (
<ScrollView>
<Text>{article_title}</Text>
</ScrollView>
)}
</SafeAreaView>
);
}

Related

React Native Cannot update during an existing state transition (such as within `render`). Render methods should be a pure function of props and state

Im learning react native, and i try to use state, now im facing an issue "Cannot update during an existing state transition (such as within render). Render methods should be a pure function of props and state."
Here my code
class Quantity extends React.Component {
constructor(props) {
super(props);
this.state = {
qty:1
};
this.setQty = this.setQty.bind(this);
}
setQty = (e) =>{
this.setState({
qty:e,
});
}
componentDidMount() {
this.props.onRef(this)
this.state.qty = 1
}
componentWillUnmount() {
this.props.onRef(undefined)
}
getCheckoutQty() {
return this.state.qty.toString();
}
minusQty = () => {
let newQty = this.state.qty -1;
this.setQty(newQty)
}
plusQty = () => {
let newQty = this.state.qty +1;
this.setQty(newQty);
}
render() {
const {qty}=this.state
return (
<View style={styles.row}>
<TouchableOpacity style={styles.icon}
disabled={(this.state.qty==1)?true:false}
// onPress={() => this.minusQty()}
>
<Icon name="minus" color="#000" style={(this.state.qty==1)?{opacity:0.2}:{opacity:1}}/>
</TouchableOpacity>
<Input
style={styles.qtyBox}
keyboardType="numeric"
returnKeyType="done"
value={qty.toString()}
onChangeText={(e)=>this.setQty(this)}
/>
<TouchableOpacity style={styles.icon}
// onPress={() => this.plusQty()}
>
<Icon name="plus" color="#000" />
</TouchableOpacity>
</View>
);
}
}
any way to fix it?
Thank for the support

How can I hide/show components by touching not button but screen on React Native?

I'm learning React Native for the first time. I want to implement a function to show/hide the component by touching the screen, not a specific button.
(Please check the attached file for the example image.)
enter image description here
In this code, I've tried to make a function. if I touch the screen (<View style={style.center}>, then show/hide the renderChatGroup() and renderListMessages() included in <View style={style.footer}>. The source code is below.
In my code, it works. However, the two <View> tag is not parallel. the footer view is center View's child.
I want to make them parallel. but I couldn't find the contents about controlling another <View> tag, not a child. In this code, I used setState, then I couldn't control another the below <View>.
Of course, I tried Fragment tag, but it didn't render anything.
How could I do implement this function? Please help me!
export default class Streamer extends React.Component {
constructor(props) {
super(props);
this.state = {
isVisibleFooter: true,
};
}
renderChatGroup = () => {
const { isVisibleFooter } = this.state;
if (isVisibleFooter) {
return (
<ChatInputGroup
onPressHeart={this.onPressHeart}
onPressSend={this.onPressSend}
onFocus={this.onFocusChatGroup}
onEndEditing={this.onEndEditing}
/>
);
}
return null;
};
onPressVisible = () => {
const { isVisibleFooter } = this.state;
this.setState(() => ({ isVisibleFooter: !isVisibleFooter }));
};
render() {
return (
<SafeAreaView style={styles.container}>
<SafeAreaView style={styles.contentWrapper}>
<View style={styles.header} />
<TouchableWithoutFeedback onPress={this.onPressVisible}>
<View style={styles.center}>
<View style={styles.footer}>
{this.renderChatGroup()}
{this.renderListMessages()}
</View>
</View>
</TouchableWithoutFeedback>
</SafeAreaView>
</SafeAreaView>
);
}
}
Firstly I would highly recommend you use react native with functional components and React Hooks as they alternative will soon will be deprecated.
Since onPress is not available on the View Component, you would need to replace it with TouchableWithoutFeedback as you have already done in your code.
For Showing/Hiding a view you would need to use a conditional operator.
export default class Streamer extends React.Component {
constructor(props) {
super(props);
this.state = {
isVisibleFooter: true,
};
}
renderChatGroup = () => {
const { isVisibleFooter } = this.state;
if (isVisibleFooter) {
return (
<ChatInputGroup
onPressHeart={this.onPressHeart}
onPressSend={this.onPressSend}
onFocus={this.onFocusChatGroup}
onEndEditing={this.onEndEditing}
/>
);
}
return null;
};
onPressVisible = () => {
this.setState(() => ({ isVisibleFooter: !isVisibleFooter }));
const { isVisibleFooter } = this.state;
};
render() {
return (
<SafeAreaView style={styles.container}>
<SafeAreaView style={styles.contentWrapper}>
<View style={styles.header} />
<TouchableWithoutFeedback onPress={this.onPressVisible}>
<View style={styles.center}>
{isVisibleFooter && <View style={styles.footer}>
{this.renderChatGroup()}
{this.renderListMessages()}
</View>}
</View>
</TouchableWithoutFeedback>
</SafeAreaView>
</SafeAreaView>
);
}
}
Here you can see i have replaced
<View style={styles.footer}>
{this.renderChatGroup()}
{this.renderListMessages()}
</View>
with
{isFooterVisible && <View style={styles.footer}>
{this.renderChatGroup()}
{this.renderListMessages()}
</View>}
stating that to only display the Footer View when
const isFooterVisible = true;

How to get value from TextInput using state in react native?

I am trying to implement TextInput and I stuck in moment when I need to get text from this.
I tried a lot of options from other StackOverflow questions but nothing works for me.
This is my code where I am using TextInput:
export default class HomeScreen extends Component {
constructor(props) {
super(props)
this.state = {
text: ''
};
}
show = () => {
console.log(this.state.text)
}
render() {
return (
<View>
<View style={{backgroundColor: 'purple', height: '100%'}}>
<View>
<Button title={'test'} onPress={this.show}></Button>
<MyTextInput
btn={1}
placeholder={'test'}
isDateTime={false}
onChangeText={(value) => this.setState({text: value})
value={this.state.text} />
</View>
</View>
</View>
)
}
and here is MyTextInput code:
export function MyTextInput(props) {
const [show, setShow] = useState(false);
const btn = props.btn;
const inputType = () => {
if(props.isDateTime) {
setShow(true);
}
else {
setShow(false);
}
}
return (
<View style={btn ? styles.container : styles.container2}>
<TextInput
style={btn ? styles.input : styles.input2}
{...this.props}
placeholder={props.placeholder}
onFocus={inputType}
showSoftInputOnFocus={props.isDateTime ? false : true} />
{show && (
<DTPicker />
)}
</View>
);
}
When I hit the button I get this:
[Info] 06-01 07:24:59.158 6962 7031 I ReactNativeJS:
Where is my mistake or what I should do different?
you need to pass onChangeText={(value) => props.onChangeText(value)} in TextInput
export function MyTextInput(props) {
const [show, setShow] = useState(false);
const btn = props.btn;
const inputType = () => {
if(props.isDateTime) {
setShow(true);
}
else {
setShow(false);
}
}
return (
<View style={btn ? styles.container : styles.container2}>
<TextInput
onChangeText={(value) => props.onChangeText(value)}
style={btn ? styles.input : styles.input2}
{...this.props}
placeholder={props.placeholder}
onFocus={inputType}
showSoftInputOnFocus={props.isDateTime ? false : true} />
{show && (
<DTPicker />
)}
</View>
);
}

How to use TouchableOpacity to hide view by in React Native?

I'm really new to React Native and I'm wondering how can I hide/show View
Here's my test code:
class Counter extends React.Component{
state = { count:0 };
setCount = () => this.setState(
prevState => ({ ...prevState, count: this.state.count + 1 })
)
render(){
const { count } = this.state;
const [valueLocation, onChangeText] = React.useState('Pleas input Address');
const [value, onChangeEvent] = React.useState('Your questions');
return (
<ScrollView style={styles.header}>
<View style={styles.box1}>
<View style={styles.box2}>
<View style={styles.user}>
<Image
style={styles.userImg}
source={{
uri: event.user[0].image,
}}
/>
<View style={styles.userText}>
<Text style={styles.username}>{event.user[0].name}</Text>
<Text style={styles.date}>{event.user[0].date}</Text>
</View>
</View>
<View style={styles.boxHidebtn}>
<View style={styles.EventClass}>
<Text style={styles.btn_text_white}>類型</Text>
</View>
<TouchableOpacity
style={styles.EventOpen}
onPress={this.setCount}
>
<Text>></Text>
</TouchableOpacity>
</View>
</View>
<View style={count % 2 ? styles.box3 : styles.box3Open}>
<Text style={styles.address}>台北市市民大道六段37號</Text>
<Text style={styles.eventShow}>路上坑洞造成積水</Text>
</View>
</View>
</ScrollView>
);
}
}
const App = () => {
<Counter/>
};
const styles = StyleSheet.create({
....
});
export default App;
I run my code and it tell me
"App(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null.
thanks!!!!!!!!
It looks like your arrow function needs to return the Counter:
const App = () => {
return <Counter/>;
};
Or, simply:
const App = () => <Counter/>;
I can see three errors in your code:
const App = () => {
return <Counter/>; // here you should return Counter
};
prevState -> this.state I guess
setCount = () => this.setState({ ...this.state, count: this.state.count + 1 }); // here
you have also a syntax error <Text>></Text> remove this extra closing > inside touchableopacity
Regarding your question in the title? I can't see where you want to hide the view?

fetch API call in react native is not working when I load the screeen

I have made an App in react native. My app makes API calls to my webserver and then Displays information based on that. The problem Is when I first load this screen... I get the loading screen and the information is display in the way it is supposed to but when I leave the screen and then comeback to the screen, it shows nothing and my array containing the items is empty, hence I think I am having problems with the API call when I leave the screen and then come back.
I am using React navigation 5 in My App.
export default function ({ navigation }) {
const [openQueries, setOpenQueries] = useState([]);
const [isLoading, seIsLoading] = useState(true);
const open_queries = [];
function getOpenQueries() {
var retrieveData = async () => {
try {
var value = await AsyncStorage.getItem("user");
var data = JSON.parse(value);
return data.user._id;
} catch (error) {
alert(error);
}
};
retrieveData().then((user) => {
fetch(URL + "/api/contact/open_queries", {
method: "POST",
body: "user=" + user + "&status=open",
headers: { "Content-type": "application/x-www-form-urlencoded" },
})
.then((response) => {
return response.json();
})
.then((responseJson) => {
if (responseJson.error === null) {
setOpenQueries(responseJson.open_queries);
seIsLoading(false);
}
});
});
}
getOpenQueries();
openQueries.forEach((query) => {
open_queries.push(
<TouchableOpacity
onPress={() =>
navigation.navigate("Chat", {
id: query._id,
title: query.title,
query: query,
showInput: true,
})
}
>
<View style={styles.inboxItem}>
<Text style={styles.inboxTitle}>{query.title}</Text>
<Text style={styles.inboxSubtext}>
{query.chats[query.chats.length - 1].chat}
</Text>
<View style={styles.lineBreak}></View>
</View>
</TouchableOpacity>
);
});
return (
<SafeAreaView style={styles.container}>
<Text style={styles.title}>Contacts</Text>
<TouchableOpacity
style={styles.button}
onPress={() => navigation.navigate("NewQuery")}
>
<Text style={styles.text}>Start a new query</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => navigation.navigate("ClosedQueries")}>
<View style={styles.button}>
<Text style={styles.text}>Closed Queries</Text>
</View>
</TouchableOpacity>
<Text style={styles.subTitle}>Open Queries</Text>
{isLoading ? (
<View style={styles.loader}>
<Code />
</View>
) : (
<ScrollView style={{ paddingTop: 10 }}>
{openQueries.length > 0 ? (
open_queries
) : (
<Text style={styles.noQuery}>No Open Queries found</Text>
)}
</ScrollView>
)}
<ScrollView></ScrollView>
<BottomNavigation navigation={navigation} active={"contact"} />
</SafeAreaView>
);
}
Try this way
export default function ({ navigation }) {
const [openQueries, setOpenQueries] = useState([]);
const [isLoading, seIsLoading] = useState(true);
const [open_queries_views, setOpenQueriesViews] = useState([]);
function getOpenQueries() {
....
}
// Similar to componentDidMount
useEffect(() => {
getOpenQueries();
});
function renderViews(){
const open_queries = [];
openQueries.forEach((query) => {
open_queries.push(
<TouchableOpacity> ... </TouchableOpacity>
);
});
setOpenQueriesViews(open_queries); // set state here to auto reflect on view
}
return (
<SafeAreaView style={styles.container}>
....
<ScrollView style={{ paddingTop: 10 }}>
{open_queries_views.length > 0 ? (
open_queries_views
) : (
<Text style={styles.noQuery}>No Open Queries found</Text>
)}
</ScrollView>
.....
</SafeAreaView>
);
}