I'm trying to make Infinite scrolling and used React-Waypoint.
I would like to show {this._renderList() } infinitely.
but It still didn't work.
I'm using YTS API, and It seems has page and limit Parameter... Do you guys have Idea of how can I show data infinitely?
this is the link of yts API
https://yts.am/api#list_movies
import React, {Component} from 'react';
import L_MovieList from './L_MovieList';
import L_Ranking from './L_Ranking';
import './L_Right_List.css';
import Waypoint from 'react-waypoint';
class L_BoxOffice extends Component {
state = {
currentPage: 0,
data : []
};
constructor(props) {
super(props);
this.state = {
movies: []
}
this._renderRankings = this._renderRankings.bind(this);
this._renderList = this._renderList.bind(this);
}
componentWillMount() {
this._getMovies();
}
_renderRankings = () => {
const movies = this.state.movies.map((movie, i) => {
console.log(movie)
return <L_Ranking title={movie.title_english} key={movie.id} genres={movie.genres} index={i}/>
})
return movies
}
_renderList = () => {
fetch(`https://yts.am/api/v2/list_movies.json?sort_by=download_count&page=${this.state.currentPage}`)
.then((res) => this.setState((prevState) => ({currentPage: prevState.currentPage + 1, data: res.body}));
const movies = this.state.movies.map((movie) => {
console.log(movie)
return <L_MovieList title={movie.title_english} poster={movie.medium_cover_image} key={movie.id} genres={movie.genres} language={movie.language} runtime={movie.runtime} year={movie.year} rating={movie.rating} likes={movie.likes} trcode={movie.yt_trailer_code}/>
})
return movies
}
_getMovies = async () => {
const movies = await this._callApi()
this.setState({
movies
})
}
_callApi = () => {
return fetch('https://yts.am/api/v2/list_movies.json?sort_by=download_count&limit=10').then(potato => potato.json())
.then(json => json.data.movies)
.catch(err => console.log(err))
}
getNextPage = () => {
fetch(`https://yts.am/api/v2/list_movies.json?sort_by=download_count&page=${this.state.currentPage}`).
then((res) => this.setState((prevState) => ({currentPage: prevState.currentPage + 1, data: res.body}));
}
render() {
const {movies} = this.state;
let sub_title;
let right_information;
if (this.props.page == 'main') {
sub_title = <div>Today Box Office</div>;
right_information = <div>
aaa</div>;
} else if (this.props.page == 'box_office') {
right_information = <div className={movies
? "L_Right_List"
: "L_Right_List--loading"}>
{this._renderList()}
{
this.state.data.map((currentData) => <div>{this._renderList()}</div>)
}
<Waypoint onEnter={this.getNextPage}/>
</div>;
}
return (<div style={{
backgroundColor: '#E5E5E5',
paddingTop: '20px',
paddingLeft: '20px'
}}>
{sub_title}
<div className={movies
? "L_Left_Ranking"
: "L_Left_Ranking--loading"}>
<div className="L_Left_Ranking_title">영화랭킹</div>
{this._renderRankings()}
</div>
{right_information}
</div>);
}
}
export default L_BoxOffice;
Related
I try to build sliders with different categories that each user has his point.
The informant comes from the json server
What I need I do not succeed in having the customer choose a user that is numbered and the dot will be colored in the slider How do I do that?
In addition he has the option to delete and return the point.
I was able to delete the points by deleting them in the object. But I could not return, is there a possibility to return?
Broker.jsx
import React, { useEffect, useState } from 'react';
import './style.css';
import Combo from '../components/Combo/Combo';
import Sliders from '../components/Sliders/Sliders';
const GetUsersDataFromManipulation = (users, field) => {
const state = users.reduce((store, user) => {
const userId = user.user
const currentManipulationUserData = user.profileManipulation[field]
if (currentManipulationUserData.length === 0) {
return store
}
store[userId] = currentManipulationUserData[0].bid
return store;
}, {})
return state;
};
function Broker({ manipulations }) {
const users = manipulations[2].users
const [hiddenUser, setHiddenUser] = useState(() => {
const visible = {};
for (let user of users) {
visible[user.user] = true;
}
return visible;
})
const GetUsersBid = (profileManipulation) => {
const data = GetUsersDataFromManipulation(users, `${profileManipulation}`); if (!Object.keys(data).length) {
return null
}
return data;
};
const gender = GetUsersBid('gender');
const age = GetUsersBid('age');
const marital = GetUsersBid('marital');
const children = GetUsersBid('children');
const education = GetUsersBid('education');
const interests = GetUsersBid('interests');
const dynamicInterests = GetUsersBid('dynamicInterests');
const showUser = (user_id) => {
const new_hidden = { ...hiddenUser }
new_hidden[user_id] = true;
setHiddenUser(new_hidden);
}
const hideUser = (user_id) => {
const new_hidden = { ...hiddenUser }
console.log(user_id)
new_hidden[user_id] = false;
setHiddenUser(new_hidden);
}
const [userInformation, setUserInformation] = useState([
{ name: 'gender', bids: gender },
{ name: 'age', bids: age },
{ name: 'marital', bids: marital },
{ name: 'children', bids: children },
{ name: 'education', bids: education },
{ name: 'interests', bids: interests },
{ name: 'dynamicInterests ', bids: dynamicInterests },
]);
useEffect(() => {
const curret_User_Info = [...userInformation]
for (let user of Object.keys(hiddenUser)) {
for (let i = 0; i < curret_User_Info.length; i++) {
if (curret_User_Info[i].bids !== null) {
if (hiddenUser[user] === false) {
delete curret_User_Info[i].bids[user]
}
else {
//What am I returning here? So that the bids will return?
}
}
}
}
setUserInformation(curret_User_Info)
}, [hiddenUser])
return (
<div>
<div className="button" >
{userInformation && <Combo users={users} showUser={showUser} hideUser={hideUser} userInformation={userInformation} />}
</div>
<div className='slid'>
{userInformation.map(sliderDetails => {
return (
<div className={sliderDetails.name} key={sliderDetails.name} >
{sliderDetails.bids && (<Sliders className="sliders" hiddenUserChange={hiddenUser} name={sliderDetails.name} userBids={sliderDetails.bids} setUserInformation={setUserInformation} userInformation={userInformation} />)}
</div>
)
})}
</div>
</div>
);
}
export default Broker;
ComboBox.jsx
import React, { useEffect, useRef, useState } from 'react';
import ComboBox from 'react-responsive-combo-box';
import { Button } from '#mui/material';
import 'react-responsive-combo-box/dist/index.css';
import "./style.css"
function Combo({ users, showUser, hideUser, userInformation }) {
const [selectedOption, setSelectedOption] = useState();
const [choosing, setChoosing] = useState();
useEffect(() => {
}, [users])
const onShow = () => {
showUser(users[selectedOption - 1].user)
}
const onHide = () => {
hideUser(users[selectedOption - 1].user)
}
const colorChange = (numOption) => {
const id = users[numOption - 1].user
}
return (
<div className="combo_box">
<ComboBox
onSelect={(option) => { setSelectedOption(option); colorChange(option) }}
options={[...Array.from({ length: users.length }, (_, i) => i + 1)]}
/>
<div className='button' >
<Button style={{ "marginRight": 20 }} variant="contained" onClick={onShow}>Show</Button>
<Button variant="contained" onClick={onHide}>Hide</Button>
</div>
</div>
);
}
export default Combo;
Sliders.jsx
import React, { useEffect, useState } from 'react'
import "./style.css"
import 'rc-slider/assets/index.css';
import Slider from 'rc-slider';
const Sliders = ({ hiddenUserChange, name, userBids, setUserInformation, userInformation }) => {
const [bids, setBids] = useState()
useEffect(() => {
setBids(Object.values(userBids))
}, [hiddenUserChange, userBids])
const updateFieldChanged = (newValue, e) => {//OnChanged Slider
setUserInformation(state => {
return state.map(manipulation => {
if (manipulation.name === name) {
Object.entries(manipulation.bids).forEach(([userId, bidValue], index) => {
manipulation.bids[userId] = newValue[index]
console.log(manipulation.bids[userId])
})
}
return manipulation
})
});
}
const handleChange = (event, newValue) => {
setBids(event)
};
return (
<>
<h1 className='headers'>{name}</h1>
{
<Slider
style={{ "marginRight": "20rem", "width": "30rem", "left": "20%" }}
range={true}
trackStyle={[{ backgroundColor: '#3f51b5' }]}
max={100}
RcSlider={true}
railStyle={{ backgroundColor: '#3f51b5' }}
activeDotStyle={{ left: 'unset' }}
ariaLabelForHandle={Object.keys(hiddenUserChange)}
tabIndex={(Object.keys(userBids))}
ariaLabelledByForHandle={bids}
value={(bids)}
onChange={handleChange}
onAfterChange={updateFieldChanged}
tipProps
tipFormatter
/>
}
</>
)
}
export default Sliders
enter image description here
Thank you all!
I am trying to use React Scheduler with my shifts database. The current state after trying to use hooks instead of class is that I cannot edit any field in the form. I have deleted some of the code to make it cleaner, for now I am trying only to add a shift.
React Scheduler original code:
import * as React from 'react';
import Paper from '#material-ui/core/Paper';
import { ViewState, EditingState } from '#devexpress/dx-react-scheduler';
import {
Scheduler,
Appointments,
AppointmentForm,
AppointmentTooltip,
WeekView,
} from '#devexpress/dx-react-scheduler-material-ui';
import { appointments } from '../../../demo-data/appointments';
export default class Demo extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
data: appointments,
currentDate: '2018-06-27',
addedAppointment: {},
appointmentChanges: {},
editingAppointment: undefined,
};
this.commitChanges = this.commitChanges.bind(this);
this.changeAddedAppointment = this.changeAddedAppointment.bind(this);
this.changeAppointmentChanges = this.changeAppointmentChanges.bind(this);
this.changeEditingAppointment = this.changeEditingAppointment.bind(this);
}
changeAddedAppointment(addedAppointment) {
this.setState({ addedAppointment });
}
changeAppointmentChanges(appointmentChanges) {
this.setState({ appointmentChanges });
}
changeEditingAppointment(editingAppointment) {
this.setState({ editingAppointment });
}
commitChanges({ added, changed, deleted }) {
this.setState((state) => {
let { data } = state;
if (added) {
const startingAddedId = data.length > 0 ? data[data.length - 1].id + 1 : 0;
data = [...data, { id: startingAddedId, ...added }];
}
return { data };
});
}
render() {
const {
currentDate, data, addedAppointment, appointmentChanges, editingAppointment,
} = this.state;
return (
<Paper>
<Scheduler
data={data}
height={660}
>
<ViewState
currentDate={currentDate}
/>
<EditingState
onCommitChanges={this.commitChanges}
addedAppointment={addedAppointment}
onAddedAppointmentChange={this.changeAddedAppointment}
appointmentChanges={appointmentChanges}
onAppointmentChangesChange={this.changeAppointmentChanges}
editingAppointment={editingAppointment}
onEditingAppointmentChange={this.changeEditingAppointment}
/>
<WeekView
startDayHour={9}
endDayHour={17}
/>
<Appointments />
<AppointmentTooltip
showOpenButton
showDeleteButton
/>
<AppointmentForm />
</Scheduler>
</Paper>
);
}
}
My function component code:
import React, { useState } from 'react';
import Paper from '#material-ui/core/Paper';
import { ViewState, EditingState } from '#devexpress/dx-react-scheduler';
import {
Scheduler,
Appointments,
AppointmentForm,
AppointmentTooltip,
WeekView,
ConfirmationDialog,
} from '#devexpress/dx-react-scheduler-material-ui';
const DataSheet = ( { addShift, shifts, deleteShift } ) => {
const [data, setData] = useState(shifts)
const [currentDate, setCurrentDate] = useState('2018-06-27')
const [addedAppointment, setAddedAppointment] = useState({})
const [appointmentChanges, setAppointmentChanges] = useState({})
const [editingAppointment, setEditingAppointment] = useState(undefined)
const changeAddedAppointment = (addedAppointment) => {
setAddedAppointment({ addedAppointment });
}
const changeAppointmentChanges = (appointmentChanges) => {
setAppointmentChanges({ appointmentChanges });
}
const changeEditingAppointment = (editingAppointment) => {
setEditingAppointment({ editingAppointment });
}
const commitChanges = ({ added, changed, deleted }) => {
setData ((????) => {
let { data } = data;
console.log(data); //returns undefined
if (added) {
const startingAddedId = data > 0 ? data[data.length - 1].id + 1 : 0;
data = [...data, { id: startingAddedId, ...added }];
addShift(added);
}
return { data };
});
}
return (
<Paper>
<Scheduler
data={data}
height={660}
>
<ViewState
currentDate={currentDate}
/>
<EditingState
onCommitChanges={commitChanges}
addedAppointment={addedAppointment}
onAddedAppointmentChange={changeAddedAppointment}
appointmentChanges={appointmentChanges}
onAppointmentChangesChange={changeAppointmentChanges}
editingAppointment={editingAppointment}
onEditingAppointmentChange={changeEditingAppointment}
/>
<WeekView
startDayHour={9}
endDayHour={17}
/>
<Appointments />
<AppointmentTooltip
showOpenButton
showDeleteButton
/>
<AppointmentForm />
</Scheduler>
</Paper>
);
}
export default DataSheet
App.js:
import React from 'react';
import backgroundImage from './Resources/BennyBackground.jpeg'
import Header from "./components/Header";
import { useState, useEffect } from "react"
import DataSheet from './components/DataSheet';
const containerStyle= {
width: '100vw',
height: '100vh',
backgroundImage: `url(${backgroundImage})`,
backgroundPosition: 'center',
backgroundSize: 'cover',
backgroundRepeat: 'no-repeat',
}
const App = () => {
const [shifts, setShifts] = useState([])
useEffect(() => {
const getShifts = async () => {
const shiftsFromServer = await fetchShifts()
setShifts(shiftsFromServer)
}
getShifts()
}, [])
const fetchShifts = async () => {
const res = await fetch(`http://localhost:5000/shifts/`)
const data = await res.json()
return data
}
const addShift = async (shift) => {
const startingAddedId = shifts.length > 0 ? shifts[shifts.length - 1].id + 1 : 0;
shift.id = startingAddedId;
const res = await fetch(`http://localhost:5000/shifts/`,{
method: 'POST',
headers: {
'Content-type': 'application/json'
},
body: JSON.stringify(shift)
})
const data = await res.json()
setShifts([...shifts, data])
}
return (
<div className="container"
style={containerStyle} >
<div className='secondary_container'>
<Header />
<DataSheet shifts={shifts} addShift={addShift}/>
</div>
</div>
);
}
export default App;
I know it is a lot of code and a lot to ask and I would highly appreciate help with this.
I believe the issue is that you are using setXxx as you would use this.setState. In class components, you have one function that modifies all the state (this.setState), while in function components you have a setter function for each field.
So change this:
const changeAddedAppointment = (addedAppointment) => {
setAddedAppointment({ addedAppointment });
}
to this:
const changeAddedAppointment = (addedAppointment) => {
setAddedAppointment(addedAppointment);
}
As far as the commitChanges function goes, you can do the data manipulation before using setData. Also I'm not sure that this let { data } = data would work since there is already a data field. You can try this:
const commitChanges = ({ added, changed, deleted }) => {
let newData = [...data.data];
if (added) {
const startingAddedId = newData > 0 ? newData [data.length - 1].id + 1 : 0;
newData = [...newData , { id: startingAddedId, ...added }];
addShift(added);
}
setData(newData);
};
I cant figure out why my Login component is not re-rendering what is on the page. The state is changed to loginShow after I click on a "Log In" button on top of my form.
import React from 'react';
import SignUp from '../SignUp';
import Cards from '../Articles/Cards';
import Login from '../LogIn';
export default class Gecko extends React.Component {
constructor(props) {
super(props);
this.state = { requestedPostsThatWeGotFromGecko: null, }
this.clickMe = this.clickMe.bind(this)
this.state = {
loginStatus: "loginHide",
authType: "signup"
};
this.loginClose = this.loginClose.bind(this);
this.loginOpen = this.loginOpen.bind(this);
}
loginClose(e) {
e.stopPropagation();
this.setState({
loginStatus: "loginHide"
});
}
loginOpen() {
this.setState({
loginStatus: "loginShow"
});
}
clickMe = () => {
const {requestedPostsThatWeGotFromGecko} = this.state;
this.setState({ requestedPostsThatWeGotFromGecko: !requestedPostsThatWeGotFromGecko })
}
/* mainLogIn = () => {
const {loginStatus} = this.state;
this.setState({ loginStatus: 'loginHide' })
} */
render() {
const { requestedPostsThatWeGotFromGecko } = this.state;
const { loginStatus } = this.state;
console.log(loginStatus);
// const { authType } = this.state;
// if (loginStatus === "loginHide") return <SignUp login={() => this.clickMe()} />
// if (requestedPostsThatWeGotFromGecko.props === true) return <Cards />
if (loginStatus !== "loginShow") return (
<div className="gecko">
{requestedPostsThatWeGotFromGecko ? (
<Cards />
): (
<SignUp login={() => this.clickMe()} />
)
}
</div>
);
if (loginStatus === "loginShow") return <Login />
}
}
I believe the issue lies where I am trying to set what is being displayed using the conditional operator at the end of the code above. I have included where I am setting the state and props from my other components in the code below.
const onClick = () => {
this.props.login();
console.log('rich');
}
const mainLogIn = () => {
this.setState({
loginStatus: "loginShow"
});
console.log('rich1');
console.log(this.state);
}
const onClick = () => {
this.props.login();
console.log('rich');
}
const mainSignUp = () => {
this.props.signup();
this.setState({
loginStatus: "loginHide"
});
console.log('rich2');
}
I know the state is updating because 1. the 'Loading...' is going away, I can console log this.state.images to see the array. However when the state updates and the loading goes the searchbar shows up but the Card's within CardList do not.
They do show up when I search for a correct string, but not before.
If I pass this.state.images to CardList they show up perfectly. However when I move to the filteredImages they only show up when filtered.
Any ideas? Thanks in advance.
class App extends Component {
constructor() {
super();
this.state = {
images:[],
searchfield: ''
}
}
getLabels = (image) => {
const AuthKey = key.key;
const res = axios.post(`https://vision.googleapis.com/v1/images:annotate?key=${AuthKey}`, {
requests: [
{
image:{
source:{
imageUri: `http://storage.googleapis.com/${image}`
}
},
features:[
{
type:"LABEL_DETECTION",
maxResults:10
}
]
}
]
});
res.then(function (response) {
const results = response.data.responses[0].labelAnnotations;
const ex = results.map(result => {
return result.description;
});
return ex;
});
return res;
};
componentDidMount() {
imageFiles.imageFiles.forEach(img => {
this.getLabels(img).then(result => {
const results = result.data.responses[0].labelAnnotations;
const labels = results.map(result => {
return result.description;
});
//Add new values to the state
this.setState({images:[...this.state.images, {img, labels}]});
});
})
}
onSearchChange = (event) => {
this.setState({searchfield: event.target.value});
}
render() {
const filteredImages = this.state.images.filter(image => {
return image.labels.includes(this.state.searchfield.toLowerCase());
});
// Create an array of objects to store the image path and the labels detected from Google Vision
if (this.state.images.length === 0) {
return <h1>Loading...</h1>
} else {
return (
<Grid className="App">
<SearchBox searchChange={this.onSearchChange}/>
<CardList images={filteredImages} />
</Grid>
)}
}
}
export default App;
class App extends Component {
constructor() {
super();
this.state = {
images:[],
searchfield: '',
filteredImages:[]
}
}
getLabels = (image) => {
const AuthKey = key.key;
const res = axios.post(`https://vision.googleapis.com/v1/images:annotate?key=${AuthKey}`, {
requests: [
{
image:{
source:{
imageUri: `http://storage.googleapis.com/${image}`
}
},
features:[
{
type:"LABEL_DETECTION",
maxResults:10
}
]
}
]
});
res.then(function (response) {
const results = response.data.responses[0].labelAnnotations;
const ex = results.map(result => {
return result.description;
});
return ex;
});
return res;
};
componentDidMount() {
imageFiles.imageFiles.forEach(img => {
this.getLabels(img).then(result => {
const results = result.data.responses[0].labelAnnotations;
const labels = results.map(result => {
return result.description;
});
//Add new values to the state
this.setState({images:[...this.state.images, {img, labels}]});
this.setState({filteredImages:[...this.state.images, {img, labels}]});
});
})
}
onSearchChange = (event) => {
this.setState({searchfield: event.target.value});
let filteredImages = this.state.images.filter(image => {
return image.labels.includes(this.state.searchfield.toLowerCase());
});
this.setState({filteredImages});
}
render() {
// Create an array of objects to store the image path and the labels detected from Google Vision
if (this.state.images.length === 0) {
return <h1>Loading...</h1>
} else {
return (
<Grid className="App">
<SearchBox searchChange={this.onSearchChange}/>
<CardList images={this.state.filteredImages} />
</Grid>
)}
}
}
export default App;
if i write this onPress={() => this.submit()} instead onPress={() => this.onSendBtnPressed()} i can get the text value but if i just write onPress={() => this.onSendBtnPressed()} this i can't see the text on the message list
here is my chatui
import React, { Component } from 'react';
import { connect } from 'react-redux';
import {KeyboardAvoidingView, Image, TouchableOpacity, ReactNative,
StyleSheet } from 'react-native';
import {Footer, FooterTab} from "native-base";
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-
view';
import { View, Title, Screen, ScrollView, TextInput,Text } from
'#shoutem/ui';
import Messages from '../containers/Messages';
import Input from '../containers/Input';
import { sendMessage } from '../actions';
const mapStateToProps = (state) => ({
chatHeight: state.chatroom.meta.height,
user: state.user,
});
class ChatUI extends Component {
constructor()
{
super();
this.state = {
text: '',
scrollViewHeight: 0,
inputHeight: 0
}
}
updateValue(text) {
console.warn(text)
}
componentDidMount() {
this.scrollToBottom(false);
}
componentDidUpdate() {
this.scrollToBottom();
}
onChangeText(text) {
this.setState({text: text})
};
onSendBtnPressed (text) {
return sendMessage(text, this.props.user)
this.textInput.clear();
Keyboard.dismiss();
}
onScrollViewLayout = (event) => {
const layout = event.nativeEvent.layout;
this.setState({
scrollViewHeight: layout.height
});
}
onInputLayout = (event) => {
const layout = event.nativeEvent.layout;
this.setState({
inputHeight: layout.height
});
}
scrollToBottom(animate = false) {
const { scrollViewHeight, inputHeight } = this.state,
{ chatHeight } = this.props;
const scrollTo = chatHeight - scrollViewHeight + inputHeight;
if (scrollTo > 0) {
this.refs.scroll.scrollToEnd();
}
}
_scrollToInput(reactRef) {
this.refs.scroll.scrollToFocusedInput(ReactNative.findNodeHandle(reactRef));
}
submit() {
let collection = {}
collection.text = this.state.text,
console.warn(collection);
}
render() {
return (
<Screen >
<Title style={{paddingTop: 25, paddingLeft: 10, borderBottomWidth: 0.5, backgroundColor: 'white', paddingBottom: 10}}>
<Image style={{width:80, height: 80}} source={require('../img/11.png')} />
<Text> GENERAL CHAT</Text>
</Title>
<KeyboardAwareScrollView ref="scroll"
onLayout={this.onScrollViewLayout}>
<Messages />
</KeyboardAwareScrollView>
<Footer style={{width:360,
height:30,
backgroundColor:'#fff',
borderRadius:20,
borderWidth: 0.5,
marginBottom: 3,
borderColor: 'gray',
}}>
<TextInput
onSubmitEditing = {this.onSubmitEditing}
multiline
onLayout={this.onInputLayout}
submitAction={this.onSendBtnPressed}
ref="input"
placeholder="Say something ..."
onChangeText={(text) => this.onChangeText(text, 'text')}
style={{backgroundColor: 'rgba(0,0,0,0)',
borderBottomWidth: 1.5, borderColor: '#f8f8f8', fontSize: 16, color: 'gray', paddingBottom:20}}
ref={input => { this.textInput = input; } }/>
</Footer>
<TouchableOpacity
onPress={() => this.onSendBtnPressed()}
style={{marginLeft:280, backgroundColor:'gray', width: 70, height: 30}}
title= "send"
>
</TouchableOpacity>
</Screen>
)
}
}
export default connect(mapStateToProps, {sendMessage})(ChatUI);
and here is my actions
import firebase from '../firebase';
import DeviceInfo from 'react-native-device-info';
import {Actions} from 'react-native-router-flux';
import FCM, { FCMEvent, NotificationType, WillPresentNotificationResult,
RemoteNotificationResult } from 'react-native-fcm';
import { Platform } from 'react-native';
export const addMessage = (msg) => ({
type: 'ADD_MESSAGE',
...msg
});
export const sendMessage = (text, user) => {
return function (dispatch) {
let msg = {
text: text,
time: Date.now(),
author: {
name: user.name,
avatar: user.avatar
}
};
const newMsgRef = firebase.database()
.ref('messages')
.push();
msg.id = newMsgRef.key;
newMsgRef.set(msg);
dispatch(addMessage(msg));
};
};
export const startFetchingMessages = () => ({
type: 'START_FETCHING_MESSAGES'
});
export const receivedMessages = () => ({
type: 'RECEIVED_MESSAGES',
receivedAt: Date.now()
});
export const fetchMessages = () => {
return function (dispatch) {
dispatch(startFetchingMessages());
firebase.database()
.ref('messages')
.orderByKey()
.limitToLast(20)
.on('value', (snapshot) => {
setTimeout(() => {
const messages = snapshot.val() || [];
dispatch(receiveMessages(messages))
}, 0);
});
}
}
export const receiveMessages = (messages) => {
return function (dispatch) {
Object.values(messages).forEach(msg => dispatch(addMessage(msg)));
dispatch(receivedMessages());
}
}
export const updateMessagesHeight = (event) => {
const layout = event.nativeEvent.layout;
return {
type: 'UPDATE_MESSAGES_HEIGHT',
height: layout.height
}
}
export const setUserName = (name) => {
return (dispatch) => {
dispatch({
type: 'SET_USER_NAME',
payload: name
});
};
};
export const setUserAvatar = (avatar) => ({
type: 'SET_USER_AVATAR',
avatar: avatar && avatar.length > 0 ? avatar : 'avatar.jpg'
});
export const login = () => {
return function (dispatch, getState) {
dispatch(startAuthorizing());
firebase.auth()
.signInAnonymously()
.then(() => {
const { name, avatar } = getState().user;
firebase.database()
.ref(`users/`)
.push({
name,
avatar
});
dispatch(userAuthorized());
dispatch(fetchMessages());
});
}
}
export const checkUserExists = () => {
return function (dispatch) {
dispatch(startAuthorizing());
firebase.auth()
.signInAnonymously()
.then(() => firebase.database()
.ref(`users/${DeviceInfo.getUniqueID()}`)
.once('value', (snapshot) => {
const val = snapshot.val();
if (val === null) {
dispatch(userNoExist());
}else{
dispatch(setUserName(val.name));
dispatch(setUserAvatar(val.avatar));
startChatting(dispatch);
}
}))
.catch(err => console.log(err))
}
}
const startChatting = function (dispatch) {
dispatch(userAuthorized());
dispatch(fetchMessages());
FCM.requestPermissions();
FCM.getFCMToken()
.then(token => {
console.log(token)
});
FCM.subscribeToTopic('secret-chatroom');
FCM.on(FCMEvent.Notification, async (notif) => {
console.log(notif);
if (Platform.OS === 'ios') {
switch (notif._notificationType) {
case NotificationType.Remote:
notif.finish(RemoteNotificationResult.NewData); //other
types available: RemoteNotificationResult.NewData,
RemoteNotificationResult.ResultFailed
break;
case NotificationType.NotificationResponse:
notif.finish();
break;
case NotificationType.WillPresent:
notif.finish(WillPresentNotificationResult.All); //other
types available: WillPresentNotificationResult.None
break;
}
}
});
FCM.on(FCMEvent.RefreshToken, token => {
console.log(token);
});
}
export const startAuthorizing = () => ({
type: 'USER_START_AUTHORIZING'
});
export const userAuthorized = () => ({
type: 'USER_AUTHORIZED'
});
export const userNoExist = () => ({
type: 'USER_NO_EXIST'
});
and MessageList
import React, { Component } from 'react';
import {
ListView, Text, Row, Image,
View, Subtitle, Caption, Heading
} from '#shoutem/ui';
import moment from 'moment';
const Message = ({ msg }) => (
<Row>
<Image styleName="small-avatar top"
source={{ uri: msg.author.avatar }} />
<View styleName="vertical">
<View styleName="horizontal space-between">
<Subtitle>{msg.author.name}</Subtitle>
<Caption>{moment(msg.time).from(Date.now())}</Caption>
</View>
<Text styleName="multiline">{msg.text}</Text>
</View>
</Row>
);
const MessageList = ({ messages, onLayout }) => (
<ListView data={messages}
autoHideHeader={true}
renderRow={msg => <Message msg={msg} />}
onLayout={onLayout}
/>
);
export default MessageList;
You are not passing a text variable into your onSendButtonPressed function. It looks like you should be calling it using the following syntax:
onPress={() => this.onSendBtnPressed(someText)}
Your onSendBtnPressed() function has the return statement on the first line, so the code will not be fired underneath the return statement (not related to your question, but hope to fix any other headaches...)