Inside my react App, i have a component that shows a list of data fetched from my database.
Now i would like to refresh my component every "X" seconds so if the database values have changed, my component will show also those new values.
Here's my code...
const SingleBet = () => {
const { data } = useGetAllBetsQuery() //REDUX FETCH
return (
<Paper sx={{marginTop:"10px", background:"white"}}>
<Grid container xs={12} sx={{display:"flex", flexDirection:"row", height:"50px"}}>
//ITEMS NO NEEDED
</Grid>
{data.map((data, index) => {
return (
<Paper sx={sxPaperList} key={index}>
<Grid container rowSpacing={2} sx={sxGridContainer}>
<Grid item xs={4} >
{data.ImportoG1 > 0 ? (
<Typography variant="h6" sx={sxTypographyNames}>{data.Giocatore1}
<img src={star} alt="little_star" height="15"/></Typography>
) : (
<Typography variant="h6" sx={sxTypographyNames}>
{data.Giocatore1}
</Typography>
)}
//OTHER THINGS LIKE THIS
</Grid>
</Paper>
)
})}
</Paper>
)
}
How u can see i fetch data from my DATABASE using redux. Now i would like to refresh this component every 5 seconds so that if DATABASE changes, every 5 seconds my component refreshes and show new values
I tried playing with useEffect but i couldnt reach to get any good results. Please help me :D
Here's my useGetAllBetsQuery() code
export const liveApi = createApi({
reducerPath: "liveApi",
baseQuery: fetchBaseQuery({baseUrl: URL}),
endpoints: (builder) => ({
getAllBets: builder.query({
query: () => "live",
})
})
})
export const { useGetAllBetsQuery } = liveApi
Related
I'm new to react an am trying to create an app to use in my portfolio. Essentially the program is a menu that has access to different menus(json files: texas_pick.js, breakfast.js...), the program is meant to display the menu options in form of buttons, the buttons' details are retrieved from their respective json file. The problem that I am facing is that when making a click on a menu option the data of the last menu item is retrieved. I programmed the backend to only push the item's name and price to the database, and the frontend, to retrieve this data and display it on a table. The data retrieved is only the last button's and not any others. I believe the problem to possibly be within my button code. Any help/tips/recommendations you could give are greatly appreciated.
I clicked every menu item and only the data from the last one was retrieved
import React from 'react'
import {useEffect,useState} from 'react'
import axios from 'axios'
import Texas_Pick from '../../json_files/texas_pick.json'
import './Mid_Container.css'
function Mid_Container() {
const [items, setItems] = useState(Texas_Pick);
const [order, setOrder] = useState({
item: '',
cost: ''
})
const createOrder = () => {
axios
.post("http://localhost:5000/orders", order)
.then(res => {window.location.reload(false)})
.catch(err => console.error(err));
}
const item1 = items[0];
const item2 = items[1];
const item3 = items[2];
const item4 = items[3];
const item5 = items[4];
const item6 = items[5];
return (
<div className="Mid_Container">
<button
style={{backgroundImage: `url(${item1.image})`}}
value={order.item=item1.item,order.cost=item1.price}
onClick={createOrder}
>
<p id="pPrice">${item1.price}</p>
<p id="pItem" >{item1.item}</p>
</button>
<button
style={{backgroundImage: `url(${item2.image})`}}
value={order.item=item2.item,order.cost=item2.price}
onClick={createOrder}
>
<p id="pPrice">${item2.price}</p>
<p id="pItem" >{item2.item}</p>
</button>
<button
style={{backgroundImage: `url(${item3.image})`}}
value={order.item=item3.item,order.cost=item3.price}
onClick={createOrder}
>
<p id="pPrice">${item3.price}</p>
<p id="pItem" >{item3.item}</p>
</button>
<button
style={{backgroundImage: `url(${item4.image})`}}
value={order.item=item4.item,order.cost=item4.price}
onClick={createOrder}
>
<p id="pPrice">${item4.price}</p>
<p id="pItem" >{item4.item}</p>
</button>
</div>
)
}
export default Mid_Container
I think that you should have this approach:
function SomeComponent() {
// Mocking your datas
const [items, setItems] = React.useState([
{
price: "1",
item: "i am the first",
image: "image1.png",
},
{
price: "7",
item: "I am the second",
image: "image2.png",
},
{
price: "3",
item: "i am the third",
image: "image3.png",
},
]);
const [order, setOrder] = React.useState();
const [myResponse, setMyResponse] = React.useState();
const createOrder = (clickedItem) => {
setOrder(clickedItem);
console.log(clickedItem);
// axios
// .post("http://somewhere", clickedItem)
// .then((res) => {
// setMyResponse(res); // or setMyResponse(res.json());
// })
// .catch((err) => console.error(err));
};
console.log('Log selected order in render loop ==> ', order);
console.log('Log response in render loop ==> ', myResponse);
return (
<div>
<div className="Mid_Container">
{items.length && items.map((currItem, index) => {
return (
<button
key={index}
style={{ backgroundImage: `url(${currItem.image})` }}
onClick={() => createOrder(currItem)}
>
<p id="pPrice">${currItem.price}</p>
<p id="pItem">{currItem.item}</p>
</button>
);
})}
</div>
</div>
);
}
Mapping on your items with map function, and pass the current item to your onClickEvent.
I also think you don't need a value attribute on your buttons. It's also not the place to do operations like you do :)
You also don't have to reload the page in the "then" of your promise. React is made to do SPA (single page application), so in the "then", you can put some code like "setResult(myResponse)" to store in you component the new data you got from your API.
I am trying to make a reserving seats for my airline website. I have done a reserve seats button, when pressed, a page pops up, where it has the array of current available seats and checkboxes besides it in-order to choose your seats. All of these are going fine, but the thing is that when I checkboxes or remove the checkboxes, I need to save the values that I've checked in another array to send them back to the backend and in the backend, I am going to compare it to the previous array and remove the seats that have been chosen.
function Row(props){
const [AvailableFSeats, setfs] = useState();
const [fList,setfList]= useState([]);
const checkf= [];
useEffect(() => {
setfList(props.row.AvailableFSeats);
},[])
const handleChange = (event) => {
setState({
...state,
[event.target.name]: event.target.checked,
});
//checkf should be the array that contains the chosen seats in the current action.
if(event.target.name==="AvailableFSeats"&&event.target.checked===true){
checkf.push(event.target.label);}
}
const {AvailableFFSeats, AvailableEESeats, AvailableBBSeats} = state;
return(
<Box sx={{ display: 'flex' }}>
<FormControl sx={{ m: 3 }} component="fieldset" variant="standard">
<FormLabel component="legend">First Class Seats</FormLabel>
<FormGroup>
{fList.map(AvailableFSeats => (
<FormControlLabel
control={
<Checkbox checked={AvailableFFSeats} onChange={handleChange} name="AvailableFSeats" />
}
label={AvailableFSeats}
/>)
)}
</FormGroup>
</FormControl>
</Box>
)
}
I have been trying to fix my virtualize list issue du to too many rendering apparently...
this is happening when I go back and forth, from one item here: restaurant (restaurant screen) to the flatList with the tab bar, I have also been trying to render less items, but even when the limit is down it doesn't seems to work...
What I use
I'm using a animated bottom sheet that display the flatList on top of the mapView
what I tried
I have been looking ,and tried that out
and also that
and those issues too
I have tried to use the Hook useMemo but apparently it does work for complex stuff such as arrays, or I my config of the dependency was wrong:
const renderMemo = useMemo(() => renderItem, []) //what should be in the array? data? !isLoading ? limit ? ( the limit is change when onEndReached)
(code below)
I have tried to make a pure component of my list (renderItem)
ISSUE
I still get :
VirtualizedList: You have a large list that is slow to update - make sure your renderItem function renders components that follow React performance best practices like PureComponent, shouldComponentUpdate, etc. Object {
"contentLength": 5148.66650390625,
"dt": 4164,
"prevDt": 2313,
}
and in this particular set up after not doing anything for a while I got that error:
_Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
at [native code]:null in dispatchAction
at containers/HomeScreen.js:87:16 in fetchData
at [native code]:null in flushedQueue
at [native code]:null in invokeCallbackAndReturnFlushedQueue_
I haven't tried shouldComponentUpdate as I don't really understand it... I mean I don't know where to locate it...
where should I head now ? memo maybe?
is there a way maybe to get less render from useEffect
CODE
repo native
HomeScreen:
const renderContent = () =>
!isLoading ? (
<View style={styles.firstParentViewRenderContent}>
....
<FlatListContents
data={data}
navigation={navigation}
setLimit={setLimit}
limit={limit}
skip={skip}
setSkip={setSkip}
handleColors={handleColors}
/>
</View>
flatListContents component:
const handleLoadMore = () => {
console.trace("handleMore");
// console.log(limit);
setIsLoadingMore(true);
// if (limit > 30) setIsLoadingMore(false);
if (!isLoading) {
setLimit(limit + 10);
setIsLoadingMore(false);
}
};
// const renderMemo = useMemo(() => renderItem, []);
const renderItem = ({ item }) => {
return (
<PureCompFlatlist
item={item}
handleColors={handleColors}
navigation={navigation}
/>
);
};
return (
<FlatList
data={data}
keyExtractor={(item) => String(item.placeId)}
renderItem={renderItem}
removeClippedSubviews={true}
maxToRenderPerBatch={20}
initialNumToRender={5}
windowSize={limit}
getItemLayout={(data, index) => {
return {
length: styles.flatList.height,
offset: 25 * styles.flatList.height,
index,
};
}}
onEndReached={handleLoadMore}
onEndReachedThreshold={0.5}
// ListFooterComponent={renderFooter}
/>
PureCompFlat:
export class PureCompFlatlist extends PureComponent {
render() {
const { item, handleColors, navigation } = this.props;
return (
<TouchableOpacity
style={styles.flatList}
onPress={() =>
navigation.navigate("Restaurant", {
id: item.placeId,
name: item.name,
description: item.description,
rating: item.rating,
thumbnail: item.thumbnail,
color: handleColors(item.type),
})
}
>
<Image style={styles.flatListPic} source={{ uri: item.thumbnail }} />
<View style={styles.flatListContent}>
<View style={styles.flatListNameType}>
<Text style={styles.flatListText}>{item.name}</Text>
<Text style={styles.flatListText}>{item.type}</Text>
</View>
<Text style={styles.flatListText}>{item.rating}</Text>
<Text style={styles.flatListText} numberOfLines={2}>
{item.description}
</Text>
</View>
</TouchableOpacity>
);
}
}
thanks in advance
I am asking because the examples I've seen are all in es6 classes.
And: I refactored my es6 class to a functional component. Now no rows appear any more. And no error either. Seems like the row renderer simply renders no rows any more.
Yes, you can use function component with react-virtualized
Does it perform as well as class component? I have no idea, tell me in comment ;)
Example:
import React from 'react'
import {Grid, Typography} from '#material-ui/core'
import PackageItem from './PackageItem'
import {PackagesByCategory} from '../functions/src/types'
import {makeStyles} from '#material-ui/core/styles'
import {WindowScroller, AutoSizer, List, ListRowRenderer, CellMeasurer, CellMeasurerCache} from 'react-virtualized'
const useStyles = makeStyles(theme => ({
container: {
minHeight: "80vh",
width: "100%"
},
title: {
marginTop: 64,
},
}))
const cache = new CellMeasurerCache({
defaultHeight: 60,
fixedWidth: true
});
const PackageCategoriesList = ({packagesByCategories}: PackageCategoriesList) => {
const classes = useStyles()
if(!packagesByCategories) {
return <></>
}
const rowRender: ListRowRenderer = ({index, key, style, parent}) => {
const packageByCategory = packagesByCategories[index]
return <CellMeasurer
cache={cache}
columnIndex={0}
key={key}
overscanRowCount={10}
parent={parent}
rowIndex={index}
>
<Grid item key={key} style={style}>
<Typography variant="h1" className={classes.title}>
{packageByCategory.category.name}
</Typography>
</Grid>
</CellMeasurer>
}
return <div className={classes.container}>
<WindowScroller
scrollElement={window}>
{({height, isScrolling, registerChild, onChildScroll, scrollTop}) => (
<div className={classes.list}>
{console.log("re der list" , height, isScrolling, scrollTop)}
<AutoSizer disableHeight>
{({width}) => (
<div ref={registerChild}>
<List
autoHeight
height={height}
isScrolling={isScrolling}
onScroll={onChildScroll}
overscanRowCount={2}
rowCount={packagesByCategories.length}
rowHeight={cache.rowHeight}
rowRenderer={rowRender}
scrollTop={scrollTop}
width={width}
/>
</div>
)}
</AutoSizer>
</div>
)}
</WindowScroller>
</div>
}
export default PackageCategoriesList
I just got started with react-virtualized and setup an InfiniteLoader->AutoSizer->VirtualScroller. Unfortunately, the rows that are lazily loaded aren't getting their props immediately. They render as if the props were null or undefined. If I scroll on past them and then scroll back to them, they are rendered correctly. Also, other than the initial pre-fetched rows, if I scroll slowly, all new rows render okay. If I send the scroll wheel flying, however, it will "land" on a set of "sub-rendered" rows. Given the code below, what am I doing wrong?
import React, { PropTypes } from 'react'
import { stitch } from 'keo'
import CSSModules from 'react-css-modules'
import css from './component.scss'
import R from 'ramda'
import { Divider, Paper } from 'material-ui'
import { AutoSizer, InfiniteLoader, VirtualScroll } from 'react-virtualized'
import 'react-virtualized/styles.css'
import Row from 'components/Row'
let list = R.repeat({score: 100, volume: 999}, 10)
function isRowLoaded ({ index }) {
return !!list[index]
}
function loadMoreRows ({ startIndex, stopIndex }) {
// fake loading
list = R.insertAll(startIndex, R.repeat({score: 100, volume: 999}, stopIndex - startIndex), list)
return Promise.resolve()
}
const render = ({ props }) => (
<div>
<Paper zDepth={2}>
<Paper zDepth={2}>
</Paper>
<div>
<InfiniteLoader
isRowLoaded={isRowLoaded}
loadMoreRows={loadMoreRows}
rowCount={1000}
>
{({ onRowsRendered, registerChild }) => (
<AutoSizer>
{({ height, width }) => (
<VirtualScroll
ref={registerChild}
width={width}
height={height}
rowCount={1000}
rowHeight={72}
onRowsRendered={onRowsRendered}
rowRenderer={
({ index }) =>
<div>
<Row {...list[index]} />
<Divider />
</div>
}
/>
)}
</AutoSizer>
)}
</InfiniteLoader>
</div>
</Paper>
</div>
)
export const View = CSSModules(stitch({ render }), css)