Results do not update after a change of state - react-native

I have a problem, when I do a search, I get the data from my API, the first time I do a search, everything is fine, all the data is displayed. However, when I do a second search immediately, nothing is updated.
I put in console.log, and I see that I'm getting this data back, yet the display is not updated.
import React, { Component } from "react";
import { SafeAreaView, StyleSheet } from "react-native";
import Search from "./Component/Search";
export default class App extends Component {
render() {
return (
<SafeAreaView style={styles.container}>
<Search />
</SafeAreaView>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1
}
});
import React from "react";
import { View, TextInput, Button, FlatList, StyleSheet } from "react-native";
import LivreItem from "../Component/LivreItem";
class Search extends React.Component {
constructor(props) {
super(props);
this.inputValue = "";
this.state = { livres: [] };
}
searchBooks = async () => {
const key = "&key=XXXXXXXXXXXXXXXXXXXXXXX";
const url = "https://www.googleapis.com/books/v1/volumes?q=" + this.inputValue + key;
return fetch(url)
.then(response => response.json())
.catch(e => {
console.log("Une erreur s'est produite");
console.log(e);
});
};
getBooks = () => {
if (this.inputValue.length > 0) {
this.searchBooks()
.then(data => this.setState({ livres: data.items }))
.catch(reject => console.log(reject));
}
};
changeText = text => {
this.inputValue = text;
};
render() {
return (
<View style={styles.header_container}>
<View style={styles.sub_container}>
<TextInput
onChangeText={text => this.changeText(text)}
style={styles.input}
placeholder="Ex: Harry Potter"
/>
<Button
style={styles.button}
title="Rechercher"
onPress={() => this.getBooks()}
/>
</View>
<FlatList
style={styles.list}
data={this.state.livres}
keyExtractor={(item, index) => item + index}
renderItem={({ item }) => <LivreItem livre={item.volumeInfo} />}
/>
</View>
);
}
}
const styles = StyleSheet.create({
sub_container: {
justifyContent: "space-between",
flexDirection: "row",
marginTop: 30,
paddingRight: 10,
paddingLeft: 10
},
header_container: {
flex: 1,
flexDirection: "column",
padding: 10
},
input: {
borderRadius: 4,
borderWidth: 0.5,
borderColor: "#d6d7da",
width: 150,
paddingLeft: 5
},
button: {
borderRadius: 4
},
list: {
paddingLeft: 15,
paddingRight: 15
}
});
export default Search;
import React from "react";
import { View, StyleSheet, Image, Text } from "react-native";
class LivreItem extends React.Component {
constructor(props) {
super(props);
this.state = { livre: this.props.livre};
this.description =
this.state.livre.description === null || this.state.livre.description === undefined
? "Pas de description disponible"
: this.state.livre.description;
this.img = this.state.livre.imageLinks;
this.image =
this.img === undefined ||
this.img.smallThumbnail === undefined ||
this.img.smallThumbnail === null
? null
: this.state.livre.imageLinks.smallThumbnail;
}
render() {
return (
<View style={styles.content}>
<View>
<Image style={styles.image} source={{ uri: this.image }} />
<Image style={styles.image} source={this.image} />
</View>
<View style={styles.content_container}>
<Text style={styles.titre}>{this.state.livre.title}</Text>
<Text style={styles.description} numberOfLines={4}>
{this.description}
</Text>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
content: {
height: 125,
flexDirection: "row",
marginTop: 15
},
content_container: {
flexDirection: "column",
flexShrink: 1,
marginLeft: 10
},
image: {
width: 100,
height: 100
},
titre: {
fontWeight: "bold",
flexWrap: "wrap"
},
description: {
flexWrap: "wrap"
}
});
export default LivreItem;
Thanks.

Configure the prop extraData in Flatlist component ala:
<FlatList
extraData={this.state.livres}
/>

Pass a boolean value to the FlatList extraData.
<FlatList
extraData={this.state.refresh}
/>

Related

Fail to update parent component's state. Fail to reset form

function DateTimePick is a child function to render picked date and picked time in parent component Reservation. Currently there are two issues with the codes: 1. the form in Reservation does not reset after submit data. 2. child DateTimePick fails to update the state for 'date' and 'time' in parent Reservation. Please have a look and lemme know how to fix these. Thanks.
child function DateTimePick is below:
import React, {useState} from 'react';
import {View, Button, Platform, Text, TextInput, StyleSheet} from 'react-native';
import DateTimePicker from '#react-native-community/datetimepicker';
import { Icon } from 'react-native-elements';
import Moment from "moment";
export const DateTimePick = () => {
const [date, setDate] = useState(new Date());
const [mode, setMode] = useState('date');
const [show, setShow] = useState(false);
const onChange = (event, selectedDate) => {
const currentDate = selectedDate || date;
setShow(Platform.OS === 'ios');
setDate(currentDate);
};
const showMode = (currentMode) => {
setShow(true);
setMode(currentMode);
};
const showDatepicker = () => {
showMode('date');
};
const showTimepicker = () => {
showMode('time');
};
return (
<View>
<View style={styles.formRow}>
<Text style={styles.formLabel}> Date</Text>
<Text onPress={showDatepicker} style={styles.formItem} value_date={date.toDateString()} onChange = {(value_date) => this.props.setState({date: value_date})}><Icon type='font-awesome-5' name='calendar' color='#512DA8' />{' ' + Moment(date).format('DD-MMM-YYYY') }</Text>
</View>
<View style={styles.formRow}>
<Text style={styles.formLabel}> Time</Text>
<Text onPress={showTimepicker} style={styles.formItem} value_time={date.toTimeString()} onChange = {(value_time) => this.props.setState({time: value_time})}><Icon type='font-awesome-5' name='clock' color='#512DA8' /> {' ' + Moment(date).format('h:mm A') }</Text>
</View>
{show && (
<DateTimePicker
testID="dateTimePicker"
value={date}
mode={mode}
is24Hour={true}
display="default"
onChange={onChange}
/>
)}
</View>
);
};
//export default DateTimePick;
const styles = StyleSheet.create({
formRow: {
alignItems: 'center',
justifyContent: 'center',
flex: 1,
flexDirection: 'row',
margin: 20
},
formLabel: {
fontSize: 18,
flex: 1
},
formItem: {
flex: 1
},
modal: {
justifyContent: 'center',
margin: 20
},
modalTitle: {
fontSize: 24,
fontWeight: 'bold',
backgroundColor: '#512DA8',
textAlign: 'center',
color: 'white',
marginBottom: 20
},
modalText: {
fontSize: 18,
margin: 10
},
})
parent Reservation which produces a reservation form and a reservation input confirmed modal
import React, {Component} from 'react';
import { Text, View, ScrollView, StyleSheet, Switch, Button, TextInput, Modal} from 'react-native';
import {DateTimePick} from './DateTimePickComponent';
class Reservation extends Component {
constructor(props) {
super(props);
this.state = {
guests: 1,
smoking: false,
notes:'',
date: new Date().toDateString(),
time: new Date().toTimeString(),
showModal: false
}
}
toggleModal() {
this.setState({showModal: !this.state.showModal})
}
handleReservation() {
console.log(JSON.stringify(this.state)); //log current state
//this.setState({ // reset the form
//})
this.toggleModal();
}
resetForm() {
this.setState({
guests: 1,
smoking: false,
notes:'',
date: new Date().toDateString(),
time: new Date().toTimeString(),
showModal: false
});
}
render() {
//, transform: [{ scaleX: 3 }, { scaleY: 1.5 }] => for switch
return(
<ScrollView>
<View style={styles.formRow}>
<Text style={styles.formLabel}> Guests </Text>
<TextInput style={styles.formItem} keyboardType="numeric" placeholder="Number"
value_guests={this.state.guests}
onChangeText = {(value_guests) => this.setState({guests: value_guests})} >
</TextInput>
</View>
<View style={styles.formRow}>
<Text style={styles.formLabel}> Notes </Text>
<TextInput style={styles.formItem} keyboardType="default" placeholder="Allergy,..etc"
value_notes={this.state.notes}
onChangeText = {(value_notes) => this.setState({notes: value_notes})} >
</TextInput>
</View>
<View style={styles.formRow}>
<Text style={styles.formLabel}> Non-Smoking </Text>
<Switch style={{ flex: 1, backgroundColor: "orange", paddingLeft:0, marginLeft:0 }} trackColor={{true: 'red', false: 'grey'}}
value={this.state.smoking}
onValueChange = {(value) => this.setState({smoking: value})} />
<Text style={styles.formLabel}> Smoking </Text>
</View>
<DateTimePick />
<View style={styles.formRow}>
<Button
onPress={() => this.handleReservation()}
title="Reserve"
color="#512DA8"
accessibilityLabel="Learn more about this purple button"
/>
</View>
<Modal animationType={'slide'} transparent={false} visible={this.state.showModal}
onDismiss={() => {this.toggleModal()}}
onRequestClose={() => {this.toggleModal()}}>
<View style={styles.modal}>
<Text style={styles.modalTitle}>Your Reservation</Text>
<Text style={styles.modalText}>Number of Guests: {this.state.guests}</Text>
<Text style={styles.modalText}>Notes: {this.state.notes}</Text>
<Text style = {styles.modalText}>Smoking?: {this.state.smoking ? 'Yes' : 'No'}</Text>
<Text style = {styles.modalText}>Date and Time: {this.state.date} {this.state.time}</Text>
<Button
onPress = {() =>{this.toggleModal(); this.resetForm();}}
color="#512DA8"
title="Close"
/>
</View>
</Modal>
</ScrollView>
);
}
}
const styles = StyleSheet.create({
formRow: {
alignItems: 'center',
justifyContent: 'center',
flex: 1,
flexDirection: 'row',
margin: 20
},
formLabel: {
fontSize: 18,
flex: 1
},
formItem: {
flex: 1
},
modal: {
justifyContent: 'center',
margin: 20
},
modalTitle: {
fontSize: 24,
fontWeight: 'bold',
backgroundColor: '#512DA8',
textAlign: 'center',
color: 'white',
marginBottom: 20
},
modalText: {
fontSize: 18,
margin: 10
},
})
export default Reservation;
you could fix it by transfering state consts date, show, mode to parent Reservation
then pass state change functions to the DateTimePick component in props like below
<DateTimePick onDateChange={(date) => this.setState({date: date}) } />
and in DateTimePick component:
const onChange = (event, selectedDate) => {
const currentDate = selectedDate || date;
setShow(Platform.OS === 'ios');
props.onDateChange(currentDate);
};
also dont forget to pass props in the component like
export const DateTimePick = (props) => {
Solved it. For using child data to update parents' state need to pass a handler for setting the state of parent to child, refer How to update parent's state in React?
class Parent extends React.Component {
constructor(props) {
super(props)
this.handler = this.handler.bind(this)
}
handler() {
this.setState({
someVar: 'some value'
})
}
render() {
return <Child handler = {this.handler} />
}
}
class Child extends React.Component {
render() {
return <Button onClick = {this.props.handler}/ >
}
}
In implementation, a handler is inserted into parent class Reservation as below
...
class Reservation extends Component {
constructor(props) {
...
this.handler = this.handler.bind(this)
}
handler(selectedDate) {
this.setState({
date: Moment(selectedDate).format('DD-MMM-YYYY'),
time: Moment(selectedDate).format('h:mm A'),
})
}
...
In child DateTimePick, embed the handler in onChange to pass child update from onChange to state update in parent Reservation like this
...
export const DateTimePick = (props) => {
const handler = props.handler;
...
const onChange = (event, selectedDate) => {
...
handler(currentDate);
};
...
...

How to use Redux in my React native Application

Here Home.js is Shows the both screen names
And Here Student.js screen is show only student contact numbers and Teacher.js
This is my full code..
And I have used navigation version 4
Navigation.js
import { createAppContainer } from 'react-navigation'
import { createStackNavigator } from 'react-navigation-stack'
import Home from '../screens/Home'
import Teacher from '../screens/Teacher'
import Student from '../screens/Student'
const StackNavigator = createStackNavigator(
{
Student: {
screen: Student
},
Home: {
screen: Home
},
Teacher: {
screen: Teacher
}
},
{
initialRouteName: 'Home',
headerMode: 'none',
mode: 'modal'
}
)
export default createAppContainer(StackNavigator)
Home.js
import React from 'react';
import { Text, View, TouchableOpacity, StyleSheet } from 'react-native';
export default class Home extends React.Component {
render() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text style={{ marginTop: 50, fontSize: 25 }}>Home!</Text>
<View
style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<TouchableOpacity
style={styles.button}
onPress={() => this.props.navigation.navigate('Teacher')}>
<Text>Teacher Numbers</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.button}
onPress={() => this.props.navigation.navigate('Student')}>
<Text>Student Numbers</Text>
</TouchableOpacity>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
button: {
alignItems: 'center',
backgroundColor: '#DDDDDD',
padding: 10,
width: 300,
marginTop: 16,
},
});
Student.js
import React, { useState } from 'react'
import { StyleSheet, View, Button, FlatList } from 'react-native'
import { Text, FAB, List, IconButton, Colors, TextInput } from 'react-native-paper'
import { useSelector, useDispatch } from 'react-redux'
import { addnumber, deletenumber } from './../store/actions/studentList'
import Header from '../components/Header'
function StudentNumber({ navigation }) {
const [studentNumber, setStudentNumber] = useState('')
const snumbers = useSelector(state => state)
const dispatch = useDispatch()
const addNumber = number => dispatch(adbnumber(number))
const deleteNumber = id => dispatch(deletenumber(id))
function onSaveNumber() {
addNumber({studentNumber})
}
function FlatListItemSeparator () {
return (
//Item Separator
<View style={{height: 0.5, width: '100%', backgroundColor: '#C8C8C8'}}/>
);
};
function GetItem(item) {
//Function for click on an item
Alert.alert(item);
}
return (
<>
<View style={styles.container}>
<Button title="Go back" onPress={() => navigation.goBack()} />
<TextInput
label='Add a Number Here'
value={studentNumber}
mode='outlined'
onChangeText={setStudentNumber}
style={styles.title}
/>
{bnumbers.length === 0 ? (
<View style={styles.titleContainer}>
<Text style={styles.title}>You do not have any student numbers</Text>
</View>
) : (
<FlatList
data={snumbers}
ItemSeparatorComponent={FlatListItemSeparator}
renderItem={({ item }) => (
<List.Item
title={item.number.studentNumber}
descriptionNumberOfLines={1}
titleStyle={styles.listTitle}
onPress={() => deletestudentNumber(item.bid)}
/>
)}
keyExtractor={item => item.id.toString()}
/>
)}
<FAB
style={styles.fab}
small
icon='plus'
label='Add new number'
onPress={() => onSaveNumber()}
/>
</View>
</>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
paddingHorizontal: 10,
paddingVertical: 20
},
titleContainer: {
alignItems: 'center',
justifyContent: 'center',
flex: 1
},
title: {
fontSize: 20
},
fab: {
position: 'absolute',
margin: 20,
right: 0,
bottom: 10
},
listTitle: {
fontSize: 20
}
})
export default Student
Teacher.js
import React, { useState } from 'react'
import { StyleSheet, View, Button, FlatList } from 'react-native'
import { Text, FAB, List, IconButton, Colors, TextInput } from 'react-native-paper'
import { useSelector, useDispatch } from 'react-redux'
import { addnumber, deletenumber } from './../store/actions/teacherList'
import Header from '../components/Header'
function Teacher({ navigation }) {
const [teacherNumber, setTeacherNumber] = useState('')
const numbers = useSelector(state => state)
const dispatch = useDispatch()
const addNumber = number => dispatch(addnumber(number))
const deleteNumber = id => dispatch(deletenumber(id))
function onSaveNumber() {
addNumber({ teacherNumber})
}
function FlatListItemSeparator () {
return (
//Item Separator
<View style={{height: 0.5, width: '100%', backgroundColor: '#C8C8C8'}}/>
);
};
function GetItem(item) {
//Function for click on an item
Alert.alert(item);
}
return (
<>
<View style={styles.container}>
<Button title="Go back" onPress={() => navigation.goBack()} />
<TextInput
label='Add a Number Here'
value={teacherNumber}
mode='outlined'
onChangeText={setTeacherNumber}
style={styles.title}
/>
{numbers.length === 0 ? (
<View style={styles.titleContainer}>
<Text style={styles.title}>You do not have any teacher numbers</Text>
</View>
) : (
<FlatList
data={numbers}
ItemSeparatorComponent={FlatListItemSeparator}
renderItem={({ item }) => (
<List.Item
title={item.number.teacherNumber}
descriptionNumberOfLines={1}
titleStyle={styles.listTitle}
onPress={() => deleteNumber(item.id)}
/>
)}
keyExtractor={item => item.id.toString()}
/>
)}
<FAB
style={styles.fab}
small
icon='plus'
label='Add new number'
onPress={() => onSaveNumber()}
/>
</View>
</>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
paddingHorizontal: 10,
paddingVertical: 20
},
titleContainer: {
alignItems: 'center',
justifyContent: 'center',
flex: 1
},
title: {
fontSize: 20
},
fab: {
position: 'absolute',
margin: 20,
right: 0,
bottom: 10
},
listTitle: {
fontSize: 20
}
})
export default Teacher
studentStore.js
import { createStore } from 'redux'
import studentReducer from '../actions/studentList'
const studentStore = createStore(studentReducer)
export default studentStore
teacherStore.js
import { createStore } from 'redux'
import teacherReducer from '../actions/teacherList'
const teacherStore = createStore(teacherReducer)
export default teacherStore
teacherReducer.js
import remove from 'lodash.remove'
export const ADD_NUMBER = 'ADD_NUMBER'
export const DELETE_NUMBER = 'DELETE_NUMBER'
let numberID = 0
export function addnumber(number) {
return {
type: ADD_NUMBER,
id: numberID++,
number
}
}
export function deletenumber(id) {
return {
type: DELETE_NUMBER,
payload: id
}
}
const initialState = []
function teacherReducer(state = initialState, action) {
switch (action.type) {
case ADD_NUMBER:
return [
...state,
{
id: action.id,
number: action.number
}
]
case DELETE_NUMBER:
const deletedNewArray = remove(state, obj => {
return obj.id != action.payload
})
return deletedNewArray
default:
return state
}
}
export default teacherReducer
studetnReducer.js
import remove from 'lodash.remove'
export const ADD_NUMBER = 'ADD_NUMBER'
export const DELETE_NUMBER = 'DELETE_NUMBER'
let numberID = 0
export function addnumber(number) {
return {
type: ADD_NUMBER,
id: numberID++,
number
}
}
export function deletenumber(id) {
return {
type: DELETE_NUMBER,
payload: id
}
}
const initialState = []
function studentReducer(state = initialState, action) {
switch (action.type) {
case ADD_NUMBER:
return [
...state,
{
id: action.id,
number: action.number
}
]
case DELETE_NUMBER:
const deletedNewArray = remove(state, obj => {
return obj.id != action.payload
})
return deletedNewArray
default:
return state
}
}
export default studentReducer
I Have tried this but is working only for Teachers not for both..

How to use ScrollToIndex in React Native?

I use a FlatList to display search results.
<View>
<FlatList
data={this.state.films}
keyExtractor={(item) => item.id.toString()}
renderItem={({item}) => <FilmItem film={item}/>}
/>
</View>
However, when the user starts a second search, this list does not restart to index 0. So I would like to add ScrollToIndex or viewPosition. I tried this but it doesn't work :
<View>
<FlatList
data={this.state.films}
keyExtractor={(item) => item.id.toString()}
renderItem={({item}) => <FilmItem film={item}/>}
scrollToItem={(index) => {0}}
/>
</View>
Could you please explain me why this is wrong and what would be the best solution ?
Thanks a lot,
Try this... I made a bunch of changes and have put comments:
// Components/Search.js
import React from "react";
import {StyleSheet, View, TextInput, Button, Text, FlatList, ActivityIndicator} from "react-native";
import FilmItem from "./filmItem";
import {getFilmsFromApiWithSearchedText} from "../API/TMDBApi";
class Search extends React.Component {
flatListRef = null; // declaring this here to make it explicit that we have this available
constructor(props) {
super(props);
this.searchedText = "";
this.state = {
films: [],
isLoading: false,
};
}
_loadFilms = () => {
// needs to be an arrow function so `this` is bound to this component
this.scrollToIndex(); // assumed you meant to actually call this?
if (this.searchedText.length > 0) {
this.setState({isLoading: true});
getFilmsFromApiWithSearchedText(this.searchedText).then(data => {
this.setState({
films: data.results,
isLoading: false,
});
});
}
};
// needs arrow to use `this`
_searchTextInputChanged = text => {
this.searchedText = text;
};
// needs arrow to use `this`
_displayLoading = () => {
// better to return null if not loading, otherwise return loading indicator
if (!this.state.isLoading) return null;
return (
<View style={styles.loading_container}>
<ActivityIndicator size='large' />
</View>
);
};
scrollToIndex = () => {
// you previously had this inside another method
this.flatListRef && this.flatListRef.scrollToIndex({index: 1}); // checking it exists first
};
render() {
return (
<View style={styles.main_container}>
<TextInput
style={styles.textinput}
placeholder='Titre du film'
onChangeText={text => this._searchTextInputChanged(text)}
onSubmitEditing={this._loadFilms} // no need to create a new anonymous function here
/>
<Button title='Rechercher' onPress={this._loadFilms} />
<View>
<FlatList
data={this.state.films}
ref={ref => (this.flatListRef = ref)}
keyExtractor={item => item.id.toString()}
onEndReachedThreshold={1} // corrected typo
onEndReached={() => {
console.log("TOC");
}}
renderItem={({item}) => <FilmItem film={item} />}
/>
</View>
{this._displayLoading()}
</View>
);
}
}
const styles = StyleSheet.create({
main_container: {
marginTop: 60,
padding: 15,
flex: 1,
},
loading_container: {
position: "absolute",
left: 0,
right: 0,
top: 100,
bottom: 0,
alignItems: "center",
paddingTop: 50,
backgroundColor: "white",
},
textinput: {
height: 50,
borderColor: "#999999",
borderWidth: 1,
paddingLeft: 5,
},
});
export default Search;
Using this code as example:
import React, { Component } from 'react';
import { Text, View, FlatList, Dimensions, Button, StyleSheet } from 'react-native';
const { width } = Dimensions.get('window');
const style = {
justifyContent: 'center',
alignItems: 'center',
width: width,
height: 50,
flex: 1,
borderWidth: 1,
};
const COLORS = ['deepskyblue','fuchsia', 'lightblue '];
function getData(number) {
let data = [];
for(var i=0; i<number; ++i)
{
data.push("" + i);
}
return data;
}
class ScrollToExample extends Component {
getItemLayout = (data, index) => (
{ length: 50, offset: 50 * index, index }
)
getColor(index) {
const mod = index%3;
return COLORS[mod];
}
scrollToIndex = () => {
let randomIndex = Math.floor(Math.random(Date.now()) * this.props.data.length);
this.flatListRef.scrollToIndex({animated: true, index: randomIndex});
}
scrollToItem = () => {
let randomIndex = Math.floor(Math.random(Date.now()) * this.props.data.length);
this.flatListRef.scrollToIndex({animated: true, index: "" + randomIndex});
}
render() {
return (
<View style={styles.container}>
<View style={styles.header}>
<Button
onPress={this.scrollToIndex}
title="Tap to scrollToIndex"
color="darkblue"
/>
<Button
onPress={this.scrollToItem}
title="Tap to scrollToItem"
color="purple"
/>
</View>
<FlatList
style={{ flex: 1 }}
ref={(ref) => { this.flatListRef = ref; }}
keyExtractor={item => item}
getItemLayout={this.getItemLayout}
initialScrollIndex={50}
initialNumToRender={2}
renderItem={({ item, index}) => (
<View style={{...style, backgroundColor: this.getColor(index)}}>
<Text>{item}</Text>
</View>
)}
{...this.props}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1
},
header: {
paddingTop: 20,
backgroundColor: 'darkturquoise',
alignItems: 'center',
justifyContent: 'center'
}
});
export default class app extends Component {
render() {
return <ScrollToExample
data={getData(100)}
/>
}
}
I tried to add a ref but it doesn't work :
// Components/Search.js
import React from 'react'
import { StyleSheet, View, TextInput, Button, Text, FlatList, ActivityIndicator } from 'react-native'
import FilmItem from './filmItem'
import { getFilmsFromApiWithSearchedText } from '../API/TMDBApi'
class Search extends React.Component {
constructor(props) {
super(props)
this.searchedText = ""
this.state = {
films: [],
isLoading: false,
}
}
_loadFilms() {
{this.scrollToIndex}
if (this.searchedText.length > 0) {
this.setState({isLoading: true})
getFilmsFromApiWithSearchedText(this.searchedText).then(data => {
this.setState({
films: data.results,
isLoading: false
})
})
}
}
_searchTextInputChanged(text) {
this.searchedText = text
}
_displayLoading() {
if (this.state.isLoading) {
return (
<View style={styles.loading_container}>
<ActivityIndicator size='large'/>
</View>
)
}
scrollToIndex = () => {
this.flatListRef.scrollToIndex({index: 1});
}
}
render() {
return (
<View style={styles.main_container}>
<TextInput
style={styles.textinput}
placeholder='Titre du film'
onChangeText={(text) => this._searchTextInputChanged(text)}
onSubmitEditing={() => this._loadFilms()}
/>
<Button title='Rechercher' onPress={() => this._loadFilms()} />
<View>
<FlatList
data={this.state.films}
ref={(ref) => { this.flatListRef = ref; }}
keyExtractor={(item) => item.id.toString()}
onEndReachedThreashold={1}
onEndReached={() => {console.log("TOC")}}
renderItem={({item}) => <FilmItem film={item}/>}
/>
</View>
{this._displayLoading()}
</View>
)
}
}
const styles = StyleSheet.create({
main_container: {
marginTop: 60,
padding: 15,
flex: 1,
},
loading_container: {
position: 'absolute',
left: 0,
right: 0,
top: 100,
bottom: 0,
alignItems: 'center',
paddingTop: 50,
backgroundColor: 'white',
},
textinput: {
height: 50,
borderColor: '#999999',
borderWidth: 1,
paddingLeft: 5,
}
})
export default Search
I'm sur I am doing something wrong, but don't find the error. Thanks a lot for your help.

Using dynamic styles in react native

I've a couple of buttons in my react native app, on pressing any button, color should change. Code is as given below
import React, { Component } from 'react';
import {
StyleSheet,
Text,
View,
TextInput,
Button,
TouchableHighlight,
Image,
Alert
} from 'react-native';
export default class Home extends Component {
constructor(props) {
super(props);
this.state= {
clicks: 0,
show: true,
isbuttonpress: false
};
}
onButtonState = () => {
this.setState({isbuttonpress: true});
}
render() {
return (
<View style={ [styles.container] }>
<Text style= { [styles.header] }>How likely is it that you would recommend this company to a friend or colleague?</Text>
<TouchableHighlight style = { [styles.buttonContainer, this.state.isbuttonpress?styles.gobackred:styles.goback] } onPress = { () => this.onButtonState() }>
<Text style = { styles.gobacktext }>0</Text>
</TouchableHighlight>
<TouchableHighlight style = { [styles.buttonContainer, this.state.isbuttonpress?styles.gobackred:styles.goback] } onPress = { () => this.onButtonState() }>
<Text style = { styles.gobacktext }>1</Text>
</TouchableHighlight>
<TouchableHighlight style = { [styles.buttonContainer, this.state.isbuttonpress?styles.gobackred:styles.goback] } onPress = { () => this.onButtonState() }>
<Text style = { styles.gobacktext }>2</Text>
</TouchableHighlight>
<TouchableHighlight style = { [styles.buttonContainer, this.state.isbuttonpress?styles.gobackred:styles.goback] } onPress = { () => this.onButtonState() }>
<Text style = { styles.gobacktext }>3</Text>
</TouchableHighlight>
<TouchableHighlight style = { [styles.buttonContainer, this.state.isbuttonpress?styles.gobackred:styles.goback] } onPress = { () => this.onButtonState() }>
<Text style = { styles.gobacktext }>4</Text>
</TouchableHighlight>
<TouchableHighlight style = { [styles.buttonContainer, this.state.isbuttonpress?styles.gobackred:styles.goback] } onPress = { () => this.onButtonState() }>
<Text style = { styles.gobacktext }>5</Text>
</TouchableHighlight>
<TouchableHighlight style = { [styles.nextContainer, styles.goback] } onPress = { () => this.onNextButtonState() }>
<Text style = { styles.gobacktext }>Next</Text>
</TouchableHighlight>
</View>
);
}
}
const styles = StyleSheet.create({
header: {
fontSize: 20,
alignItems: 'center',
padding: 20,
},
container: {
alignItems: 'center',
justifyContent: 'center'
},
buttonContainer: {
height:45,
justifyContent: 'center',
alignItems: 'center',
marginBottom:20,
width:45,
}, gobackred: {
backgroundColor: "#00a2b2",
},
goback: {
backgroundColor: "#00b5ec",
},
gobacktext: {
color: 'white',
},
nextContainer: {
height:45,
marginTop: 15,
justifyContent: 'center',
alignItems: 'center',
marginBottom:20,
width:250,
borderRadius:30,
}
})
Layout is as given below:
Whenever any option is selected, color of that button should change. But in my code, color of all buttons changes when clicked on any button. How can I fix it?
This happens because you used one state this.state.isbuttonpress for all button try to make the component of this code.
your TouchableHighlight Component
DemoButton.js
import React, { Component } from "react";
import { View, Text, TouchableHighlight } from "react-native";
export default class DemoButton extends Component {
constructor(props) {
super(props);
this.state = { isbuttonpress: false };
}
onButtonState = () => {
this.setState({ isbuttonpress: !this.state.isbuttonpress });
};
render() {
return (
<View>
<TouchableHighlight
style={{ backgroundColor: this.state.isbuttonpress ? "red" : "blue" }}
onPress={this.onButtonState}
>
<Text>{this.props.buttonTitle}</Text>
</TouchableHighlight>
</View>
);
}
}
App.js
import DemoButton from "./DemoButton";
export default class Heal extends Component {
constructor(props) {
super(props);
this.state = { isbuttonpress: false };
}
render() {
return (
<View>
<Header />
<DemoButton buttonTitle="0"/>
<DemoButton buttonTitle="1"/>
<DemoButton buttonTitle="2"/>
<DemoButton buttonTitle="3"/>
<DemoButton buttonTitle="4"/>
<DemoButton buttonTitle="5"/>
</View>
)
}
}

How to access mock data array inside FlatList react native

export const Artists = [
{
name: "Breakbot",
songs: [
{
title: "Star Tripper",
album: "Still Waters",
},
{
title: "You Should Know (feat. Ruckazoid)",
album: "Still Waters",
},
]
},]
Above is mock data array which is defined in another file. And I have declared flatlist in another file.
SmapleScreen.js
import React, { Component } from 'react'
import { Text, View, FlatList, TouchableOpacity, RefreshControl } from 'react-native'
import { connect } from 'react-redux'
// Add Actions - replace 'Your' with whatever your reducer is called :)
import Icon from 'react-native-vector-icons/MaterialIcons';
import { Fonts, Colors, Images, Metrics } from '../Themes'
import MockData from "./mockData"
// Styles
import styles from './Styles/OrdersScreenStyle'
class SampleScreen extends Component {
constructor(props) {
super(props);
this.state = {
}
}
componentWillMount() {
}
render() {
// console.log(this.props.order_details.new_orders,'refreshed' )
return (
(this.props.order_details.new_orders == null || this.props.order_details.new_orders.length == 0) ?
<View style={{ flex: 1, justifyContent: "center", backgroundColor: Colors.snow }}>
<Text style={{ alignSelf: 'center' }}>
You do not have any orders.
</Text>
</View>
:
<View style={{ flex: 1, flexDirection: 'column', justifyContent: "flex-start" }}>
<View style={{ padding: 10, flexDirection: 'row' }}>
<Text style={{ flex: 3 }}>Scheme</Text>
<Text style={{ flex: 2 }}>Amount</Text>
</View >
<FlatList
style={styles.container}
data={MockData}
keyExtractor={(item, index) => index}
renderItem={(item) => this.getOrderComponent(item)}
/>
<View>
<PrimaryButton label="Make Payment"
disabled={this.props.submitFetching} fetching={this.props.submitFetching} onPress={this.onMakePaymentClick} />
</View >
</View>
)
}
getOrderComponent=(item)=>{
return (
<View>
<Text>{item.name}</Text>
</View>
)
}
}
const mapStateToProps = (state, ownProps) => {
return {
}
}
const mapDispatchToProps = (dispatch) => ({
})
export default connect(mapStateToProps, mapDispatchToProps)(SmapleScreen)
MockData.js
const data =[
{
name: "Breakbot",
songs: [
{
title: "Star Tripper",
album: "Still Waters",
},
{
title: "You Should Know (feat. Ruckazoid)",
album: "Still Waters",
},
]
},
]
export default data