it makes a flat list of rooms and inside those rooms are messages. So I want to long press on a specific room in the list, and when i do this, I want to delete a room.
onLongPress={() => this.roomsRef.remove({item})}
I thought the above would work, but it fails. I put it in the render row part. It comes up saying Reference.remove failed. first argument must be a valid function. Like inside these rooms it has messages and I think thats where im going wrong but im not sure how to go about it. thank you
'use strict'
import React, { Component, useEffect } from 'react';
import { Text, Image, TextInput, TouchableHighlight, StatusBar, FlatList, View, TouchableOpacity, Dimensions, LogBox, Alert } from 'react-native';
// import firebaseApp from './firebaseConfig.js';
import firebaseApp from '../config/firebasekeys';
import {SafeAreaView} from 'react-native-safe-area-context'
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view'
import {Avatar} from 'react-native-elements'
import { color } from 'react-native-reanimated';
const DeviceHeight = Dimensions.get('screen').height
const DeviceWidth = Dimensions.get('screen').width
class Rooms extends Component {
static navigationOptions = {
title: 'Rooms',
};
constructor(props) {
super(props);
var firebaseDB = firebaseApp.database();
this.roomsRef = firebaseDB.ref('rooms'); // rooms collection
this.state = {
rooms: [],
newRoom: ''
}
}
// maybe its this.roomsRef.remove(item.name) or maybe its name idk hmmm
componentDidMount() {
LogBox.ignoreLogs(['VirtualizedLists should never be nested']); // doing this to ignore the log box error for scroll view
this.listenForRooms(this.roomsRef);
}
listenForRooms(roomsRef) {
roomsRef.on('value', (dataSnapshot) => {
var roomsFB = [];
dataSnapshot.forEach((child) => {
roomsFB.push({
name: child.val().name,
key: child.key
});
});
this.setState({ rooms: roomsFB });
});
}
addRoom() {
if (this.state.newRoom === '') {
return
}
this.roomsRef.push({ name: this.state.newRoom });
this.setState({ newRoom: '' });
}
openMessages(room) {
this.props.navigation.navigate("Messages", {roomKey: room.key, roomName: room.name});
}
renderRow(item) {
return (
<TouchableOpacity
onPress={() => this.openMessages(item)}
onLongPress={() => this.roomsRef.remove({name:item})}
>
<Text style={{
color: 'orange',
fontSize: 22,
}}>{item.name}</Text>
</TouchableOpacity>
)
}
render() {
return (
<SafeAreaView style={styles.container}>
<StatusBar style="auto"/>
<KeyboardAwareScrollView>
<View>
<View >
<TextInput>
}}
placeholder={"enter chat name"}
onChangeText={(text) => this.setState({newRoom: text})}
value={this.state.newRoom}
/>
<TouchableHighlight
style={{
marginRight: 20
}}
onPress={() => this.addRoom()}
>
>
</TouchableHighlight>
</View>
<View>
<FlatList
data={this.state.rooms}
renderItem={({item}) => (this.renderRow(item)
)}
/>
</View>
{/* <View>
<FlatList
data={this.state.rooms}
renderItem={({item}) => (this.renderRow(item)
)}
/>
</View> */}
</View>
</KeyboardAwareScrollView>
</SafeAreaView>
);
}
}
export default Rooms;
I recommend keeping the reference docs for the API handy as you're developing, as there are quite a few problems you can catch that way. For example, the Reference.remove() method doesn't take an item as its argument (in fact: it typically is called without arguments).
To delete a specific node, you should build a reference to that node, and then call remove() on the reference:
roomsRef.child("keyOfRoomToRemove").remove()
Related
Everything is ok but when clicking month then got the error: Attempt to invoke interface method 'int com.facebook.react.bridge.readablearray.size()' on a null object reference.
This is the Call page:
import React from 'react';
import { SafeAreaView, View, StatusBar, Alert } from 'react-native';
import {
Layout,
Icon, Divider, Text,
TopNavigation, TopNavigationAction,
Datepicker } from '#ui-kitten/components';
const MenuIcon = (props) => (
<Icon {...props} name='menu' style={{width: 36, height: 36, color: 'gray', alignItems: 'center'}}/>
);
export const PatrolScreen = ({ navigation }) => {
const [date, setDate] = React.useState(new Date());
const MenuAction = () => (
<TopNavigationAction icon={MenuIcon} onPress={navigation.toggleDrawer}/>
);
return (
<Layout style={{ flex: 1 }}>
<StatusBar hidden={false} />
<TopNavigation title='Patrol' alignment='center' accessoryLeft={MenuAction}/>
<Divider/>
<Layout style={{ flex: 1}}>
<Datepicker
date={date}
onSelect={nextDate => setDate(nextDate)}
/>
</Layout>
</Layout>
);
};
The following is my App.js:
import React from 'react';
import * as eva from '#eva-design/eva';
import { ApplicationProvider, IconRegistry } from '#ui-kitten/components';
import { IoniconsPack } from './utils/ion-icons';
import { MaterialCommunityIconsPack } from './utils/materialcommunity-icons';
import { AppNavigator } from './routes/navigation';
import { ThemeContext } from './utils/theme.context';
export default () => {
const [theme, setTheme] = React.useState('dark');
const toggleTheme = () => {
const nextTheme = theme === 'light' ? 'dark' : 'light';
setTheme(nextTheme);
};
return (
<>
<IconRegistry icons={[IoniconsPack, MaterialCommunityIconsPack]} />
<ThemeContext.Provider value={{ theme, toggleTheme }}>
<ApplicationProvider {...eva} theme={eva[theme]}>
<AppNavigator />
</ApplicationProvider>
</ThemeContext.Provider>
</>
);
};
How to resolve this? Thanks.
How do I make Materia-UI GridList Face vertically in One Row on Mobile?
My GridList is two in a row which is what I wanted but when I inspect it on mobile it still shows two in a row instead of One. that means it's not responsive, How do I make it responsive?
this is my Events Component.
import React from "react";
import { Link } from "react-router-dom";
import axios from "axios";
import GridList from "#material-ui/core/GridList";
import GridListTile from "#material-ui/core/GridListTile";
import GridListTileBar from "#material-ui/core/GridListTileBar";
import ListSubheader from "#material-ui/core/ListSubheader";
mport IconButton from "#material-ui/core/IconButton";
import Button from "#material-ui/core/Button";
import { withStyles } from "#material-ui/core/styles";
import Typography from "#material-ui/core/Typography";
const useStyles = (theme) => ({
root: {
display: "flex",
flexWrap: "wrap",
justifyContent: "space-around",
overflow: "hidden",
backgroundColor: theme.palette.background.paper,
},
gridList: {
width: 1000,
height: 950,
},
icon: {
color: "rgba(255, 255, 255, 0.54)",
},
});
class EventsList extends React.Component {
constructor(props) {
super(props);
this.state = { events: [] };
}
componentDidMount() {
axios
.get("http://localhost:9000/events/")
.then((response) => {
this.setState({ events: response.data });
})
.catch(function (error) {
console.log(error);
});
}
render() {
const { classes } = this.props;
return (
<div className={classes.root}>
<GridList cellHeight={330} className={classes.gridList} spacing={8}>
<GridListTile key="Subheader" cols={2} style={{ height: "auto" }}>
<ListSubheader component="div">December</ListSubheader>
</GridListTile>
{this.state.events.map((tile) => (
<GridListTile key={tile.eventImage}>
<img src={tile.eventImage} alt={tile.title} />
<GridListTileBar title={tile.title} titlePosition="top" />
<GridListTileBar
paragraph={tile.description}
actionIcon={
<IconButton
aria-label={`info about ${tile.title}`}
className={classes.icon}
></IconButton>
}
/>
</GridListTile>
))}
</GridList>
</div>
);
}
}
export default withStyles(useStyles)(EventsList);
this is the List of my events displayed by GridList on Mobile
but something like this is what I want to see when I am on Mobile.
Since you are using class based component, you can use withWidth to conditionally set cols value to GridList.
See working example here in codesandbox
Example code snippet
class TitlebarGridList extends Component {
render() {
const { classes, width } = this.props; // <---- see here
let columns = width === "xs" || width === "sm" ? 1 : 2;
console.log("=========>", width);
return (
<div className={classes.root}>
<GridList cellHeight={200} className={classes.gridList} cols={columns}> {/* //<---- see here */}
<GridListTile key="Subheader" cols={3} style={{ height: "auto" }}>
<ListSubheader component="div">December</ListSubheader>
</GridListTile>
{tileData.map(tile => (
<GridListTile key={tile.title}>
<img className={classes.image} src={tile.img} alt={tile.title} />
</GridListTile>
))}
</GridList>
</div>
);
}
}
TitlebarGridList.propTypes = {
classes: PropTypes.object.isRequired
};
export default compose(
withStyles(styles, {
name: "TitlebarGridList"
}),
withWidth() //<---- see here
)(TitlebarGridList);
Note: withWidth will be deprecated sometime in the future, so consider to use useMediaQuery hook (in that case you have to switch to functional component).
I am new to React and I load all the data from my database initially on page load but there is info I need to find in an array and apparently it isn't instant. What do I need to do to make sure the render method only renders the objects when the object promises have resolved?
I haven't tried much... I'm really stuck here.
This seems different than the other problems I've read here because I load a bunch on info in the beginning just fine but I need to call some team information every time a function is called so it isn't as simple as loading it once because the object i need is always different.
This code is the main issue. I also included the full file below:
I did some modification to the code in a edit: I realized that I just need to call the opponent team because I have the player team already.
if (team.id === game.team_1) {
var redTeam = team;
// set blueTeam based on game.team_1
// firebase.teams().doc('teams/{game.team_2}')
} else {
var blueTeam = team;
// set redTeam based on game.team_1
// firebase.teams().doc('teams/{game.team_1}')
}
Full file:
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import Async from 'react-promise'
import { withFirebase } from '../Firebase';
// import * as ROUTES from '../../constants/routes';
import { Container, Image, Spinner, Col, Row, Card, Accordion, Button } from 'react-bootstrap'
class PlayerGameList extends Component {
constructor(props) {
super(props);
this.state = {
loadingTeams: false,
loadingSchedule: false,
teams: [],
schedule: []
};
}
componentDidMount() {
this.setState({
loadingTeams: true,
loadingSchedule: true,
});
this.unsubscribe = this.props.firebase
.teams()
.where('players', 'array-contains', '-LXkkB7GNvYrU4UkUMle')
.onSnapshot(snapshot => {
let teams = [];
snapshot.forEach(doc =>
teams.push({ ...doc.data(), uid: doc.id }),
);
this.setState({
teams,
loadingTeams: false,
});
});
this.unsubscribe2 = this.props.firebase
.schedule()
.onSnapshot(snap => {
let schedule = [];
snap.forEach(doc =>
schedule.push({ ...doc.data(), uid: doc.id }),
);
this.setState({
schedule,
loadingSchedule: false,
});
});
}
componentWillUnmount() {
this.unsubscribe();
this.unsubscribe2();
}
render() {
const { teams, schedule, loadingTeams, loadingSchedule } = this.state;
return (
<div>
<h2>Games</h2>
{loadingTeams && loadingSchedule && <div colSpan="12"><Spinner animation="border" role="status">
<span className="sr-only">Loading...</span>
</Spinner></div>}
{/* CONTENT */}
<Container fluid>
<Row>
{getTeams({ teams, schedule })}
</Row>
</Container>
</div >
);
}
}
function getTeams({ teams, schedule }) {
if (!teams) {
return null;
}
if (!teams.length) {
return null;
} else {
return teams.map(team => getGames({ team, schedule }))
}
}
function getGames({ team, schedule }) {
schedule.sort((a, b) => (a.time > b.time) ? -1 : 1)
if (!schedule) {
return null;
}
if (!schedule.length) {
return null;
} else {
return schedule.map(game => guts({ team, game }));
}
}
function guts({ team, game }) {
const image = {
height: '25px',
width: '25px'
}
if (team.id === game.team_1) {
var redTeam = team;
// set blueTeam based on game.team_1
// firebase.teams().doc('teams/{game.team_2}')
} else {
var blueTeam = team;
// set redTeam based on game.team_1
// firebase.teams().doc('teams/{game.team_1}')
}
if (game.team_1 === team.id || game.team_2 === team.id) {
var time = new Date(game.time.seconds * 1000);
var dateFormat = require('dateformat');
var finalTime = dateFormat(time, 'ddd mmm dd, h:MM tt')
return (
<Col lg='4' md='6' sm='12' key={game.uid} style={{ marginBottom: '15px' }}>
<Card>
<Card.Body>
<Row>
<Image src={team.logo} style={image} roundedCircle />
<p>{team.name}</p>
<div style={{ height: '25px', width: '25px', backgroundColor: 'red' }}></div>
</Row>
<Row>
<Image src={team.logo} style={image} roundedCircle />
<p>{team.name}</p>
<div style={{ height: '25px', width: '25px', backgroundColor: 'blue' }}></div>
</Row>
<Row>
<div>
{finalTime}
</div>
</Row>
</Card.Body>
<Accordion>
<Card style={{ margin: '0', padding: '0' }}>
<Card.Header>
<Accordion.Toggle as={Button} variant="link" eventKey="0">
Show Match IDs
</Accordion.Toggle>
</Card.Header>
<Accordion.Collapse eventKey="0">
<Card.Body>{game.match_id}</Card.Body>
</Accordion.Collapse>
</Card>
</Accordion>
</Card>
</Col>
);
}
}
export default withFirebase(PlayerGameList);
The items all load blank then a few seconds later all the console logs come through with the array objects. When I tell it to await the program just throws an error.
I can't make my prop render in HTML. I'm making an app for a Christian ministry and I want to be able to post like a blog, I got quill working but I can't show the results rendered, is showing pure HTML.
I'v been trying to follow the rules of react-render-html, but my experience is little, so I don't really know what I'm missing. I try use 'renderHTML' but it doesn't work.
Below is my code, and if you see the screenshot, you will see that the first card is showing the HTML tags.
import React from 'react';
import { Container, Card, Button, CardTitle, CardText, CardColumns, CardSubtitle, CardBody, Collapse } from 'reactstrap';
import { CSSTransition, TransitionGroup } from 'react-transition-group';
import { connect } from 'react-redux';
import { getPosts, deletePost } from '../actions/postActions';
import PropTypes from 'prop-types';
import axios from 'axios';
import renderHTML from 'react-render-html';
import PostsForm from './extentions/PostsForm';
class Home extends React.Component {
componentDidMount() {
this.props.getPosts();
}
onDeleteClick = (id) => {
this.props.deletePost(id);
}
constructor(props) {
super(props);
this.onEntering = this.onEntering.bind(this);
this.onEntered = this.onEntered.bind(this);
this.onExiting = this.onExiting.bind(this);
this.onExited = this.onExited.bind(this);
this.toggle = this.toggle.bind(this);
this.state = {
collapse: false,
status: 'Closed',
ButtonText: "Submit Post"
};
}
onEntering() {
this.setState({ status: 'Opening...' });
}
onEntered() {
this.setState({ status: 'Opened' });
}
onExiting() {
this.setState({ status: 'Closing...' });
}
onExited() {
this.setState({ status: 'Closed', ButtonText: "Submit Post" });
}
toggle() {
this.setState(state => ({ collapse: !state.collapse, ButtonText: "Close" }));
}
formOpening = () => {
this.setState({
on: !this.state.on
})
}
render(){
const { posts } = this.props.post;
return(
<Container>
<div style={{float: "left"}}><h5>Current state: {this.state.status}</h5></div>
<div style={{float: "right"}}><Button
color="dark"
style={{marginButtom: '2rem'}}
onClick={this.toggle}>{this.state.ButtonText}</Button></div>
<Collapse
isOpen={this.state.collapse}
onEntering={this.onEntering}
onEntered={this.onEntered}
onExiting={this.onExiting}
onExited={this.onExited}
style={{clear: "both"}}
>
<Card>
<CardBody>
<PostsForm />
</CardBody>
</Card>
</Collapse>
<CardColumns style={{clear: "both"}}>
<TransitionGroup className="Posts">
{posts.map(({ _id, title, subtitle, postbody}) => (
<CSSTransition key={_id} timeout={500} classNames="fade">
<Card>
<CardBody>
<Button className="remove-btn" color="danger" size="sm" onClick={this.onDeleteClick.bind(this, _id)}>×</Button>
<CardTitle><h3>{title}</h3></CardTitle>
<CardSubtitle><h4>{subtitle}</h4></CardSubtitle>
<CardText>{postbody}</CardText>
<Button>Read More</Button>
</CardBody>
</Card>
</CSSTransition>
))}
</TransitionGroup>
</CardColumns>
</Container>
)
}
};
Home.propTypes = {
getPosts: PropTypes.func.isRequired,
post: PropTypes.object.isRequired
}
const mapStateToProps = (state) => ({
post: state.post
});
export default connect(mapStateToProps, { getPosts, deletePost })(Home);
Screenshot of how it looks now
I would like to see that the cards are acting like
Body Text ect etc etc not <p>Body Text ect etc etc</p>
You need to use dangerouslySetInnerHTML API.
From React Docs, slightly modified:
function createMarkup(html) {
return {__html: html};
}
function MyComponent({html}) {
return <div dangerouslySetInnerHTML={createMarkup(html)} />;
}
https://reactjs.org/docs/dom-elements.html
This is my login function which gets executed after clicking login button
login=()=>{
fetch('http://192.168.0.101:9090/Shakehands',{
method:'post',
headers:{
'Accept':'application/json',
'Content-type':'application/json',
},
body:JSON.stringify({
email:this.email,
password:this.password,
text:"Login"
})
})
.then((responseData)=>{
return responseData.json();
})
.then((responseData)=>{
//console.log(responseData);
//alert(this.state.insdata)
if(responseData.success==true){
this.props.navigation.navigate('Home');
}
else{
alert(responseData.message);
}
}).done();
}
This is my node.js backend
con.query('SELECT * from Shakehands where email=? AND password=?',[email,password],function(error,rows,fields){
if(!!error) console.log(error);
if(rows.length>0){
res.send({'success':true,'message':'Welcome'})
}
else{
res.send(JSON.stringify({'success':false,'message':'User not found'}))
}
})
This is the Navigator Function
const Navigation = StackNavigator({
Splash:{
screen:Splash,
navigationOptions:{
header:null,
}
},
Login:{
screen:Login,
navigationOptions:{
header:null,
}
},
Signup:{
screen:Signup,
navigationOptions:{
header:null,
}
},
ForgetPass:{
screen:ForgetPass,
navigationOptions:{
header:null,
}
},
Home:{
screen:Home,
navigationOptions:{
header:null,
},
}
})
export default Navigation;
The login function is included in a file logtxtbox which includes text inputs and a button which in turn is included in login file.
This is the Login.js file:
import React,{Component} from 'react';
import {View,AppRegistry,StyleSheet,ScrollView,TouchableOpacity,Text,StatusBar} from 'react-native';
import Animate from '../Components/Animate';
import Logtxtbox from '../Components/Logtxtbox';
export default class Login extends Component{
render(){
return(
<ScrollView>
<View style={styles.container}>
<StatusBar backgroundColor='#1c313a'/>
<Animate />
<Logtxtbox />
<TouchableOpacity onPress={()=>this.props.navigation.navigate('ForgetPass')}>
<Text title='ForgotPassword' style={{fontSize:16 ,marginTop:10 ,
color:'white',fontWeight:'bold'}}>ForgotPassword?</Text>
</TouchableOpacity>
<Text style={styles.sign}>Don't have an acoount yet?</Text>
<TouchableOpacity onPress={()=>this.props.navigation.navigate('Signup')}>
<Text title='SignUp' style={styles.signup}>SignUp</Text>
</TouchableOpacity>
</View>
</ScrollView>
)
}
}AppRegistry.registerComponent('Login',()=>Login)
Here is the styling for the Login.js:
const styles = StyleSheet.create({
container:{
backgroundColor:'#455a64',
alignItems:'center',
height:600
},
signup:{
color:'white',
fontSize:16,
fontWeight:'bold',
textAlign:'center',
},
sign:{
textAlign:'center',
color:'white',
fontSize:16,
marginTop:20,
}
})
You have to pass this.props.navigation to inner component. You can use this part of code:
render(){
return(
...
<Logtxtbox navigation = { this.props.navigation }/>
...
)
}