I have this screen under a DrawerNavigator:
class myScreen extends Component {
state: Object;
constructor(props) {
super(props);
this.getBeers();
this.state = {
is_loading: true,
beers: null,
beers_ds: null,
}
}
componentWillUpdate(nextProps: Object, nextState: Object)
{
if(!nextState.is_loading)
{
let ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 });
nextState.beers_ds = ds.cloneWithRows(nextState.beers);
}
}
async getBeers()
{
let finalApiURL = API_BASE_URL;
let fetchResult = await fetch(finalApiURL)
let Result = await fetchResult.json();
this.setState({users: Result, is_loading: false});
}
render()
{
if(this.state.is_loading)
{
return(
<View style={{ flex: 1, backgroundColor: 'white', marginTop: 50 }}>
<Text>
Loading ...
</Text>
</View>
)
}
else
{
let renderRow = (row) => {
return (
<TouchableOpacity onPress={ () => {} }>
<View >
<Text>{row.name}</Text>
<Text style={{ color: 'blue' }}>ADD</Text>
</View>
</TouchableOpacity>
);
}
return
(
<View >
<ListView dataSource={this.state.beers_ds} renderRow={renderRow.bind(this)} />
</View>
);
}
}
}
export default myScreen;
Now when I get results back from the server, I setState(). Then, componentWillUpdate() gets called, and the else() statement in render() fires.
But my screen does not change and it stays on Loading ...
And sometimes I get see this error:
Can anyone help in finding why this weird behavior is occurring?
Thanks
EDIT:
It works when I change this:
return
(
To this:
return (
Welcome to Javascript!
I will assume that you have the latest react native so ListView is deprecated you can use FlatList (Dod) instead
change your code to be like this
renderRow = (row) => {
return (
<TouchableOpacity onPress={ () => {} }>
<View >
<Text>{row.name}</Text>
<Text style={{ color: 'blue' }}>ADD</Text>
</View>
</TouchableOpacity>
);
}
render() {
return(
<View style={{ flex: 1, backgroundColor: 'white', marginTop: 50 }}>
{this.state.is_loading ?
<Text>
Loading ...
</Text>
:
<FlatList data={this.state.users} renderItem={(item) => this.renderRow(item)} />
}
</View>
);
}
Related
So I've seen many posting the same problem, but for some I don't seem to be able to adapt the posted solutions to my case.. I hope someone can tell me exactly what changes I need to do in order to get this working, since I don't know how to implement the suggested solutions!
I am using React Native Swipeable
Example of someone having the same issue
I have a file in which I built the Swipeable Component and an other class which calls the component. I've set a timeout close function on the onSwipeableOpen as a temporary solution. But ideally it should close immediately upon pressing "delete". The "..." stands for other code which I deleted since it's not important for this case.
AgendaCard.js
...
const RightActions = ({ onPress }) => {
return (
<View style={styles.rightAction}>
<TouchableWithoutFeedback onPress={onPress}>
<View style={{ flexDirection: "row", alignSelf: "flex-end" }}>
<Text style={styles.actionText}>Löschen</Text>
<View style={{ margin: 5 }} />
<MaterialIcons name="delete" size={30} color="white" />
</View>
</TouchableWithoutFeedback>
</View>
);
};
...
export class AgendaCardEntry extends React.Component {
updateRef = (ref) => {
this._swipeableRow = ref;
};
close = () => {
setTimeout(() => {
this._swipeableRow.close();
}, 2000);
};
render() {
return (
<Swipeable
ref={this.updateRef}
renderRightActions={() => (
<RightActions onPress={this.props.onRightPress} />
)}
onSwipeableOpen={this.close}
overshootRight={false}
>
<TouchableWithoutFeedback onPress={this.props.onPress}>
<View style={styles.entryContainer}>
<Text style={styles.entryTitle}>{this.props.item.info}</Text>
<Text style={styles.entryTime}>
eingetragen um {this.props.item.time} Uhr
</Text>
</View>
</TouchableWithoutFeedback>
</Swipeable>
);
}
}
Agenda.js
...
renderItem(item) {
...
<AgendaCardAppointment
item={item}
onRightPress={() => firebaseDeleteItem(item)}
/>
...
}
I'm having the same issue and have been for days. I was able to hack through it, but it left me with an animation I don't like, but this is what I did anyways.
export class AgendaCardEntry extends React.Component {
let swipeableRef = null; // NEW CODE
updateRef = (ref) => {
this._swipeableRow = ref;
};
close = () => {
setTimeout(() => {
this._swipeableRow.close();
}, 2000);
};
onRightPress = (ref, item) => { // NEW CODE
ref.close()
// Delete item logic
}
render() {
return (
<Swipeable
ref={(swipe) => swipeableRef = swipe} // NEW CODE
renderRightActions={() => (
<RightActions onPress={() => this.onRightPress(swipeableRef)} /> // NEW CODE
)}
onSwipeableOpen={this.close}
overshootRight={false}
>
<TouchableWithoutFeedback onPress={this.props.onPress}>
<View style={styles.entryContainer}>
<Text style={styles.entryTitle}>{this.props.item.info}</Text>
<Text style={styles.entryTime}>
eingetragen um {this.props.item.time} Uhr
</Text>
</View>
</TouchableWithoutFeedback>
</Swipeable>
);
}
}
Calendar/index.js
constructor(props) {
this.state = {
CalendarModalVisible: false
};
}
toggleCalendarModal = () => {
this.setState({ CalendarModalVisible: !this.state.CalendarModalVisible });
}
setModalPage = () => {
return(
<Modal isVisible={this.state.CalendarModalVisible} onBackdropPress={() =>
{ this.toggleCalendarModal() }} >
<View style={this.style.modal_container} >
</View>
</Modal>
);
}
renderDay(day, id) {
....
return (
<TouchableOpacity onPress={() => { this.setModalPage();
this.toggleCalendarModal() }}>
<View style={[this.style.home_day, { height: days_len }]} key={day}
>
<View style={{ flex: 1, alignItems: 'center' }} key={id}>
<DayComp
...
>
{date}
</DayComp>
</View>
</View>
</TouchableOpacity>
);
renderWeek(days, id) {
const week = [];
days.forEach((day, id2) => {
week.push(this.renderDay(day, id2));
}, this);
return (<View style={[this.style.home_week} key=
{id}>{week}
</View>);
render() { ...}
return( <View
...calendar component
</View>
);
I am modifying the calendar/index.js in the react-native-calendar module.
I made the calendar page like iphone calendar.
and I want the modal page show if i click the view home_day in renderday function.....
the setModalPage function is working well, but the modal page is not showing.
how can I resolve the problem..?
Edit
I resolve the problem myself.
I added {this.forceUpdate()} in toggleCalendarModal function.
I'm still new in react native and programming, and i am trying to pass items from my flat list into a modal. What i'm about to pass is the icon, status, and description. How am i supposed to do that?
this is my flatlist
buildPanel(index, item) {
let panel = [];
let keys = DBkeys['Requests'].MyRequest;
let status = item[keys['status']];
panel.push(<View style={{ position: 'absolute', right: 0, bottom: 0, padding: normalize(5), alignItems: 'center' }} key={'status'}>
<TouchableOpacity onPress={this.handleShowModal}>
<Icon name={img.itemStatus[status].name} type={img.itemStatus[status].type} color={img.itemStatus[status].color} size={normalize(38)} />
</TouchableOpacity>
</View>);
return panel;
}
<View style={[styles.panelContainer, status === 'success' ? {} : { backgroundColor: color.white }]}>
<FlatList
showsVerticalScrollIndicator={false}
progressViewOffset={-10}
refreshing={this.state.refreshing}
onRefresh={this.onRefresh.bind(this)}
onMomentumScrollEnd={(event) => event.nativeEvent.contentOffset.y === 0 ? this.onRefresh() : null}
data={content}
renderItem={({ item }) => item}
keyExtractor={(item, key) => key.toString()}
/>
</View>
<IconModal visible={this.state.modalVisible} close={this.handleDismissModal}/>
and this is my IconModal.js
const IconModal = (props) => {
return(
<Modal
isVisible={props.visible}
onBackdropPress={props.close}
>
<View style={styles.dialogBox}>
<View style={styles.icon}>
<Icon name='open-book' type='entypo' color='#ffb732' size={normalize(70)} />
</View>
<View style={styles.text}>
<Text style={styles.status}>Status</Text>
<Text>Desc</Text>
</View>
<TouchableOpacity onPress={props.close}>
<View>
<Text style={styles.buttonText}>GOT IT</Text>
</View>
</TouchableOpacity>
</View>
</Modal>
)
}
IconModal.propTypes ={
visible: PropTypes.bool.isRequired,
close: PropTypes.func,
}
from the renderItem of your FlatList,
You must be clicking somewhere to open modal,
when you click store that whole single item in state variable,
like, if you're using TouchableOpacity then
<TouchableOpacity onPress={this.passDataToModal}/>
...
...
passDataToModal=(item)=>{
this.setState({modalData:item},()=>{
//you can open modal here
});
}
and in your modal component,
you can pass data with prop.
<IconModal modalData={this.state.modalData} visible={this.state.modalVisible} close={this.handleDismissModal}/>
and you can use these data in IconModal as this.props.modalData.
If there is more data then you can always add another prop.
Define the following Hooks in your function Component.
const [modalVisible, setModalVisible] = useState(false);
const [modalData, setModalData] = useState([]);
const [modalTitle, setModalTitle] = useState('');
Now Trigger the function which opens the Modal, while simultaneously passing data into it.
<TouchableHighlight underlayColor="skyblue" onPress={() => { openSettingsModal(title,settings) } }>
Open Modal
</TouchableHighlight>
Here is the function code -
const openSettingsModal = (title,settings) => {
setModalTitle(title);
setModalData(settings);
setModalVisible(!modalVisible);
}
And finally a snippet of the Modal Code.
<Modal animationType="none" transparent={true} visible={modalVisible} >
<View style={styles.centeredView}>
<Text> { modalTitle }</Text>
<Text> { modalData }</Text>
</View>
</Modal>
For example:
class Container extends Component {
constructor(props) {
super(props)
this.state = {
modalVisible: false,
activeItemName: '', //state property to hold item name
activeItemId: null, //state property to hold item id
}
}
openModalWithItem(item) {
this.setState({
modalVisible: true,
activeItemName: item.name,
activeItemId: item.id
})
}
render() {
let buttonList = this.props.item.map(item => {
return (
<TouchableOpacity onPress={() => { this.openModalWithItem(item) }}>
<Text>{item.name}</Text>
</TouchableOpacity>
)
});
return (
<View>
{/* Example Modal Component */}
<Modal isOpen={this.state.openDeleteModal}
itemId={this.state.activeItemId}
itemName={this.state.activeItemName} />
{buttonList}
</View>
)
}
}
The data i sent it from fetch and php , it's can be load and the result of the flat liste is none and it was only the text i wrote also i use flatliste but nothing in on the screen , i think the problem is in array sat and how to use value , key and item
import ajax from './fetchdata.js'
export class Home extends Component {
constructor(props) {
super(props);
this.state = { sat: [] };
}
async componentDidMount() {
const sat = await ajax.fetchset();
console.log(this.state.sat);
this.setState({sat});
}
render() {
return (
<View style={styles.container}>
<Text style={styles.h2text}>
Black Order
</Text>
<FlatList
data={this.state.sat}
keyExtractor={item => item.idC}
renderItem={ ({item}) => {
return (
<View style={{ flex : 1, flexDirection : "row" }}>
<View style={{ flex : .6 }}>
<Text style={{ fontSize : 20 , textColor:'red'}}>{item.nom}</Text>
</View>
<View style={{ flex : .4 }}>
<Text style={{ fontSize : 20 , textColor:'red' }}>{item.adresse} points</Text>
</View>
</View>
);
}
}
/>
</View>
);
}
}
*/
export default Home;
////////fetchdata.js
export default {
async fetchset() {
try {
let response = await fetch('http://localhost/APP/Chauffeur/Backendapp/api/Traitement/AffichageStation.php');
let responseJsonData = await response.json();
console.log("done")
return responseJsonData;
}
catch(e) {
console.log(e)
}
}
}
exepected a liste of data the adresse and nom , but the message is only the the text Black Order
I'm mapping an array to be rendered in React Native. On an event (button press) I want to add and object to the array and it be rendered on the screen. I am getting the lifecycle functions to trigger, but not sure if they are needed for this or how to utilize them effectively. Any help would be greatly appreciated!
class Home extends Component {
constructor(props) {
super(props)
this.state = {
data: '',
text: '',
submitted: false,
count: 1,
arr: [
{
key: 1,
text: "text1"
},
],
}
buttonsListArr = this.state.arr.map(info => {
return (
<View style={styles.container}>
<Text key={info.key}>{info.text}</Text>
<Button title='Touch' onPress={() => {
this.setState({count: this.state.count + 1})
}}/>
</View> )
})
}
shouldComponentUpdate = () => {
return true;
}
componentWillUpdate = () => {
this.state.arr.push({key: this.state.count, text: 'text2'})
}
render() {
return (
<View style={styles.container}>
{buttonsListArr}
</View>
)
}
}
What you've written is not typical. A quick fix is to move the logic to a render function like
constructor(props) {
.
.
this.renderText = this.renderText.bind(this)
}
renderText() {
return this.state.arr.map(info => {
return (
<View style={styles.container}>
<Text key={info.key}>{info.text}</Text>
<Button title='Touch' onPress={() => {
this.setState({count: this.state.count + 1})
}}/>
</View> )
})
}
then call the function within the render()
render() {
return (
<View style={styles.container}>
{this.renderText()}
</View>
)
}
You shouldn't be using a lifecycle call to add an element to an array. Simply call setState and it will rerender itself!
Try this.
<View style={styles.container}>
<Text key={info.key}>{info.text}</Text>
<Button title='Touch' onPress={() => {
this.setState({
count: this.state.count + 1
arr: this.state.arr.push({key: this.state.count, text: 'text2'})
})
}}/>
</View> )
return this.arrayholder.map(image => {
return (
<View style={styles.ImageContainer}>
<Image style={styles.ImageContainer} source={image} />
</View>
)
})