How Do I Correctly use CellMeasurer to set Table Column Width Based on the Content Length? - react-virtualized

I'm trying to dynamically set the column width using CellMeasurer in a dynamic created Columns.
// hoping that CellMeasurer is what I needed to adjust
// width of my table columns, but not working.
const cellRenderer = ({ columnIndex, key, parent, rowIndex, style }) => {
const content = list[rowIndex][columnHeader[columnIndex].columnName];
return (
<CellMeasurer
cache={cache}
columnIndex={columnIndex}
key={key}
parent={parent}
rowIndex={rowIndex}
>
<div
style={{
...style,
height: 35,
whiteSpace: "nowrap"
}}
>
{content}
</div>
</CellMeasurer>
);
};
const cache = new CellMeasurerCache({
defaultWidth: 100,
minWidth: 75,
fixedHeight: true
});
return (
<AutoSizer>
{({ height, width }) => (
<div width={width}>
<Table
width={width}
height={500} // why can't i use {height} here?
headerHeight={40}
rowHeight={30}
rowCount={list.length}
rowGetter={({ index }) => list[index]}
>
// Dynamically create Column
{columnHeader.map((columnData, i) => (
<Column
width={800}
onClick={this.onHeaderClick}
label={columnData.displayName}
dataKey={columnData.columnName}
cellRenderer={cellRenderer}
{...this.props}
key={i}
/>
))}
</Table>
</div>
)}
</AutoSizer>
);
Here is the example code: https://codesandbox.io/s/mzj5y255kj
I want to set the column 'News' to as long as the length in the text.
Result would be that no matter what the content length is, the column will grow.

Related

Re-fetching data automatically when Database values changes

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

Tabs in react not displaying appropriate content

I am using the Tab from semantic-ui-react. I need to display a list of days and their corresponding events for that day. However, an event created in one day shows up in the other day too.
As seen, I created an event in day 1, but it shows up in day 2, which is incorrect. Here's how I generate the tab data:
const panes = selectedDays.map((day, index) => {
const count = index + 1;
return {
menuItem: `Day ${count}`,
render: () => <Tab.Pane><Agenda day={day} index={count} /></Tab.Pane>
};
});
this.setState({ panes });
Component Code
{
currentIndex === 3 &&
<Fragment>
<Tab
menu={{ pointing: true }}
panes={this.state.panes}
/>
<Button className='formnext' onClick={this.handlePrevious}>
<FontAwesome name='angle-left' style={{ color: 'white', fontSize: '2.2rem' }} className='logout' />
</Button>
<Button className='formnext' onClick={this.handleNext}>
<FontAwesome name='angle-right' style={{ color: 'white', fontSize: '2.2rem' }} className='logout' />
</Button>
</Fragment>
}
If I add a key attribute to the Tab.Pane or Agenda component, clicking on a tab header, just clears my state and I am left with no data. Any idea how to solve this one?

Width of the Table in AutoSizer and Window Scroller is not being updated properly while resizing the browser

I am using React-Virtualized to display a table with a long list of values. So it's a combination of WindowScroller, AutoSizer and Table. I am having an issue when the browser is resized. This is my code:
render() {
return (
<WindowScroller>
{({ height, isScrolling, scrollTop }) => (
<AutoSizer>
{({ width }) => (
<Table
ref={(ref: Table) => { this.TableRef = ref; }}
autoHeight={true}
height={height}
width={width}
isScrolling={isScrolling}
scrollTop={scrollTop}
_noRowsRenderer={this._noRowsRenderer}
...
>
<Column
...
/>
</Table>
)}
</AutoSizer>)}
</WindowScroller>
);
}
When the browser is resized the width of the table is not updated accordingly and so a vertical scroll bar is being displayed although it's not needed; unless it's zoom-in or zoom-out and then it's all redrawn-positioned correctly.
Does anyone has any idea how to fix this?

Does react-virtualized work inside a functional component?

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

React-Virtualized InfiniteLoader lags on passing props to rendered rows

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)

Resources