react virtualized auto sizer does not work - javascript

I have been trying this code and it just does not work.
With AutoSizer, Row does not gets rendered.
It only starts working when I remove AutoSizer from the code.
I don't know what is wrong with the code and the docs is not helping either.
Full code:
import React, { Component } from 'react';
import Card from './Card';
import { FixedSizeList as List } from "react-window";
import AutoSizer from "react-virtualized-auto-sizer";
import memoize from "memoize-one";
const CARD_SIZE = 340;
class CardList extends Component {
getItemData = memoize((itemsPerRow, locations) => ({
itemsPerRow,
locations
}))
render() {
const { locations } = this.props;
console.log(locations.length)
const Row = ({ data, index, style }) => {
const { itemsPerRow, locations } = data;
console.log(data)
const items = [];
const fromIndex = index * itemsPerRow;
const toIndex = Math.min(fromIndex + itemsPerRow, locations.length);
for (let i = fromIndex; i < toIndex; i++) {
items.push(
<Card key={i} location={locations[i]} />
);
}
return (
<div className={'flex-auto'} style={style}>
{items}
</div>
);
}
return (
<div style={{ marginTop: "10px", height: "80%" }}>
<AutoSizer>
{
({ height, width }) => {
const itemsPerRow = Math.floor(width / CARD_SIZE) || 1;
const rowCount = Math.ceil(locations.length / itemsPerRow);
const itemData = this.getItemData(itemsPerRow, locations);
return (
<div>
<List
height={height}
itemCount={rowCount}
itemData={itemData}
itemSize={CARD_SIZE}
width={width}
>
{ Row }
</List>
</div>
);
}
}
</AutoSizer>
</div>
);
}
}
P.S. locations props is an array of images

I tried removing "react-virtualized-auto-sizer" and installed "react-virtualized"
Then,
import {AutoSizer} from 'react-virtualized';
and it works!!
But I don't want to keep react-window and react-virtualized together.
I hope the author of this package will help in fixing this problem.

Maybe it's because of height incompatibility. You can check with :
<div style={{ flex: '1 1 auto' , height: '100vh'}}>
<AutoSizer>
{({ height, width }) => {
return (
<FixedSizeList
className="List"
height={height}
itemCount={1000}
itemSize={35}
width={width}
>
{Row}
</FixedSizeList>
)
}}
</AutoSizer>
</div>

Related

Getting the error " React has detected a change in the order of Hooks called by StudentsFilter"

//StudentsFilter.jsx
import {
Accordion,
AccordionButton,
AccordionIcon,
AccordionItem,
AccordionPanel,
Badge,
Box,
Button,
Checkbox,
Flex,
Radio,
RadioGroup,
Text,
useColorMode,
useColorModeValue,
VStack,
} from "#chakra-ui/react";
import React, { useState } from "react";
import { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { axiosInstance } from "../../../axiosConfig";
import { commonSlidercss, darkSlidercss } from "../../../GlobalStyles";
import {
setFilterSearchMode,
setSearchingBatch,
setSearchingStream,
} from "../../../redux/slices/adminUserSlice";
const StudentsFilter = () => {
const [streams, setStreams] = useState(null);
const [batchYear, setBatchYear] = useState([]);
const [checkedStreams, setCheckedStreams] = useState([]);
const [checkedBatches, setCheckedBatches] = useState([]);
const siteState = useSelector((state) => state.siteReducer);
const adminUsers = useSelector((state) => state.adminUserReducer);
const filterSearchMode = adminUsers?.filterSearchMode;
const site = siteState.siteInfo;
const { colorMode } = useColorMode();
const dispatch = useDispatch();
useEffect(() => {
getStream();
let batches = [];
if (site) {
let year = site.year_established;
let current_year = new Date().getFullYear();
let year_diff = current_year - site.year_established;
for (let i = 0; i <= year_diff; i++) {
batches.push(year + i);
}
setBatchYear(batches);
}
}, [site]);
const getStream = async () => {
try {
const res = await axiosInstance.get("stream");
setStreams(res?.data?.stream);
} catch (error) {
console.log("Something went wrong while getting streams", e);
}
};
const streamsHandler = (e, li) => {
e.stopPropagation();
const index = checkedStreams.indexOf(li);
if (index > -1) {
setCheckedStreams([
...checkedStreams.slice(0, index),
...checkedStreams.slice(index + 1),
]);
} else {
setCheckedStreams([...checkedStreams, li]);
}
};
const batchesHandler = (e, li) => {
e.stopPropagation();
const index = checkedBatches.indexOf(li);
if (index > -1) {
setCheckedBatches([
...checkedBatches.slice(0, index),
...checkedBatches.slice(index + 1),
]);
} else {
setCheckedBatches([...checkedBatches, li]);
}
};
useEffect(() => {
dispatch(setSearchingStream(checkedStreams));
dispatch(setSearchingBatch(checkedBatches));
}, [checkedBatches, checkedStreams]);
return (
<Flex
p="6"
direction="column"
style={{ height: "inherit" }}
align="space-between"
justify="space-between"
w="300px"
maxH={231}
overflowY="scroll"
css={colorMode === "light" ? commonSlidercss : darkSlidercss}
>
<Box>
<Text fontWeight="medium" fontSize="sm" mb={7}>
More filters
</Text>
<Accordion allowMultiple>
<AccordionItem>
<AccordionButton>
<Box flex="1" fontSize="xs" textAlign="left">
Batch
</Box>
<AccordionIcon />
</AccordionButton>
<AccordionPanel pb={4}>
<RadioGroup>
<VStack align="start">
{batchYear &&
batchYear.map((li) => (
<Checkbox
// onChange={checkboxChange}
key={li}
value={li}
colorScheme={useColorModeValue(
"primaryScheme",
"purple"
)}
size="sm"
onChange={(e) => batchesHandler(e, li)}
isChecked={checkedBatches.includes(li)}
>
<Text fontSize="xs">{li}</Text>
</Checkbox>
))}
</VStack>
</RadioGroup>
</AccordionPanel>
</AccordionItem>
<AccordionItem>
<AccordionButton>
<Box flex="1" textAlign="left" fontSize="xs">
Stream
</Box>
<AccordionIcon />
</AccordionButton>
<AccordionPanel pb={4}>
<RadioGroup>
<VStack align="start">
{streams &&
streams.map((li) => (
<Checkbox
// onChange={checkboxChange}
key={li.id}
value={li.id}
colorScheme={useColorModeValue(
"primaryScheme",
"purple"
)}
size="sm"
onChange={(e) => streamsHandler(e, li.id)}
isChecked={checkedStreams.includes(li.id)}
>
<Text fontSize="xs">{li?.name}</Text>
</Checkbox>
))}
</VStack>
</RadioGroup>
</AccordionPanel>
</AccordionItem>
</Accordion>
</Box>
<Box>
<Button
width="full"
h="40px"
borderRadius="10px"
fontWeight="500"
variant="primary"
mt="10px"
onClick={() => dispatch(setFilterSearchMode(!filterSearchMode))}
>
Filter
</Button>
</Box>
</Flex>
);
};
export default StudentsFilter;
What is the reason why I am getting the error " React has detected a change in the order of Hooks called by StudentsFilter. This will lead to bugs and errors if not fixed" I have seen this warning in 2-3 components and also tried to correct it but I don't know what I am doing wrong? Can someone help me to identify it?
You're calling the useColorModeValue conditionally (and in a loop) in the return statement. That's probably the source of the error.
You should use ESLint and the "rules of hooks" rule, it would have been highlighted directly in your editor.

Unable to add scroll functionality

I get this error while adding a functionality to my web app.
-> so basically there are a few cards on the map and if user 'click' any of the one, the app will scroll to description of that particular card.
And I suppose the error [Violation] 'requestAnimationFrame' handler took 136ms is coming from the following code
const PlaceDetails = ({ place, selected, refProp }) => {
// console.log(place);
const classes = useStyles();
if (selected)
refProp?.current?.scrollIntoView({ behavior: "smooth", block: "start" });
return (
<Card elevation={6}>
<CardMedia
...
map.jsx
return (
<div className={classes.mapContainer}>
<GoogleMapReact
bootstrapURLKeys={{ key: process.env.REACT_APP_GOOGLE_MAPS_API_KEY }}
// get key from https://console.cloud.google.com/
defaultCenter={coordinates}
center={coordinates}
defaultZoom={14}
margin={[50, 50, 50, 50]}
options={""}
onChange={(e) => {
// console.log(e);
setCoordinates({ lat: e.center.lat, lng: e.center.lng });
setBounds({ ne: e.marginBounds.ne, sw: e.marginBounds.sw });
}}
// as we click a child (card) we want information about which child was the click from the map component all the way to the list component
onChildClick={(child) => setChildClicked(child)}
>
{places?.map((place, i) => (
<div
className={classes.markerContainer}
lat={Number(place?.latitude)}
lng={Number(place?.longitude)}
key={i}
>
List.js
import React, { useState, useEffect, createRef } from "react";
import {
CircularProgress,
Grid,
Typography,
InputLabel,
MenuItem,
FormControl,
Select,
} from "#material-ui/core";
import PlaceDetails from "../PlaceDetails/PlaceDetails";
import useStyles from "./styles";
const List = ({ places, childClicked, isLoading }) => {
const classes = useStyles();
const [type, setType] = useState("restaurants");
const [rating, setRating] = useState("");
const [elRefs, setElRefs] = useState([]);
// console.log({ places });
useEffect(() => {
const refs = Array(places?.length)
.fill()
.map((_, i) => elRefs[i] || createRef());
setElRefs(refs);
}, [places]);
return (
<div className={classes.container}>
{isLoading ? (
<div className={classes.loading}>
<CircularProgress size="5rem" />
</div>
) : (
<>
// ... other code
<Grid container spacing={3} className={classes.list}>
{places?.map((place, i) => (
<Grid item key={i} xs={12}>
<PlaceDetails
place={place}
selected={Number(childClicked) === i}
refProp={elRefs[i]}
/>
</Grid>
))}
</Grid>
</>
)}
</div>
);
};
export default List;
could somebody help me in understanding why the scroll is not working and what error chrome consoles is showing me.

how to do i map through this object in React Native?

it tried using like this
{ options.map( opt => {
return <Text>{opt.value}</Text>
}) }
Here iam taking the data from the backend and iam passing in to the DetailScreen.
class Poll extends Component {
state = {
loading:true,
pollDetails : []
}
componentDidMount(){
fetch('http://192.168.43.22:5000/api/v1/questions/5f1c31e1089847468cb9c508')
.then((response) => response.json())
.then((responseJson) => this.setState({pollDetails:responseJson.data}));
this.setState({loading:false});
}
render() {
const {loading, pollDetails} = this.state;
if(loading){
<View>
<Text><ActivityIndicator/></Text>
</View>
}
return(
<ScrollView>
<DetailsScreen
key={pollDetails._id}
title={pollDetails.title}
options={pollDetails.options}
voteCount={pollDetails.voteCount}
opinionCount={pollDetails.opinionCount}
loaded={true}
votes={60}
/>
</ScrollView>);
}
}
In Here i try to map through the options but it throws the error!
import React, {Component} from 'react';
import {View, Text, StyleSheet, Animated, TouchableOpacity} from 'react-native';
import Card from '../UI/Card';
export default class DetailScreen extends Component{
state = {
width:0,
voteCount: this.props.voteCount
}
handleOnLayout = ( {nativeEvent} ) => {
this.setState({width:nativeEvent.layout.width})
}
handleVotes = (id) => {
console.log(this.state.voteCount)
}
render(){
const {title, voteCount, votes, opinionCount, loaded} = this.props;
const _animatedWidth = new Animated.Value(0);
const animatedAnswerValue = () => {
const percentage = votes / voteCount;
const rowWidth = Math.floor(this.state.width * percentage);
Animated.timing(_animatedWidth,{
toValue:rowWidth,
duration:1500
}).start();
}
animatedAnswerValue();
const getOverlayStyles = (votes) => {
const s = [styles.optionBar];
if(votes > 50){
s.push(styles.optionBarHigh);
}
if(votes < 50 && votes > 20){
s.push(styles.optionBarMedium);
}
if(votes <= 20){
s.push(styles.optionBarLow)
}
return s;
}
return(
<View style={{marginLeft:100}}>
<Text style={{marginTop:50}}>{title}</Text>
{
this.props.options.map((opt,index) => {
return <Text key={index}>{opt.votes}</Text>
})
}
<Text>Just some sample text here!!!</Text>
{/* <TouchableOpacity key={options._id[0]} onPress={() => this.handleVotes(options._id)}>
<Card>
<Text>{options.value}</Text>
<View style={styles.optionBarRow} onLayout={this.handleOnLayout}>
<Animated.View
style={[getOverlayStyles(this.props.votes,loaded), {width:_animatedWidth}]}/>
<View style={styles.opinions}>
<Text style={{textAlign:"center"}}>Opinions</Text>
</View>
</View>
</Card>
</TouchableOpacity> */}
</View>
);
}
}
but it throw error of "Cannot read property 'map' of undefined
ive been scratching my head lately..
i'll be glad if some one sort this out for me!
thanks in advance :)
It might that data haven't been loaded on the very first render.
You can try to add an extra check for option to be in place, like:
{ options && options.map( opt => {
return <Text>{opt.value}</Text>
}) }

How to reduce the height of carousel

Front-end development is a new experience for me, for that purpose I prefer to go with react as a goto library. Now I am stuck in a problem.
Can anyone guide me on how to reduce the height of my carousel images without disrupting the quality of my pictures?
Desired output:
Here is my code,
import React from 'react';
import { Gallery, GalleryImage } from "react-gesture-gallery";
import ReactDOM from "react-dom";
const images = [
"https://scontent.fkhi2-1.fna.fbcdn.net/v/t1.0-9/77017766_759244471260597_2356862208463339520_o.jpg?_nc_cat=109&_nc_ohc=UQbWRlHdFO4AQknJyvWGAbIif0SgcS5n49AOU3TRgnqOvh9cPMwZ-uY9A&_nc_ht=scontent.fkhi2-1.fna&oh=5bba2ef0d536b1d3752a12825cac2e88&oe=5E465DD2",
"https://scontent.fkhi2-1.fna.fbcdn.net/v/t1.0-9/76727026_759558941229150_3910702859859001344_o.jpg?_nc_cat=104&_nc_ohc=jrAaYH_HT2MAQn8cSekMJqFSo9ZoXP5AQwjtn6JgZ1gDPDH1441VSIeFA&_nc_ht=scontent.fkhi2-1.fna&oh=536d5190623a82400bf8b7f11f71b7fb&oe=5E3EE66A"
];
function Home() {
const [index, setIndex] = React.useState(0);
React.useEffect(() => {
const timer = setInterval(() => {
if (index === 4) {
setIndex(0);
} else {
setIndex(prev => prev + 1);
}
}, 3000);
return () => clearInterval(timer);
}, [index]);
return (
<Gallery
style={{
background: "black",
height: "100vh",
width: "100vw"
}}
index={index}
onRequestChange={i => {
setIndex(i);
}}
>
{images.map(image => (
<GalleryImage objectFit="contain" key={image} src={image} />
))}
</Gallery>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<Home />, rootElement);
export default Home;

How to pass props and function to the react-widow list?

This is react-window plugin: https://github.com/bvaughn/react-window
I am using this to render simple list of "Rows".
This is Row comp in which I am try to pass function and const idTestProps=''
class Row extends PureComponent {
render() {
const { index, style } = this.props;
let label;
if (itemStatusMap[index] === LOADED) {
label = `Row ${index}`;
} else {
label = "Loading...";
}
return (
<div className="ListItem" style={style}>
{label}
</div>
);
}
}
This is the Container comp which should pass function and one props to the Row comp:
const outerElementType = forwardRef((props, ref) => (
<div ref={ref} onClick={handleClick} {...props} />
));
export default function App() {
return (
<Fragment>
<InfiniteLoader
isItemLoaded={isItemLoaded}
itemCount={1000}
loadMoreItems={loadMoreItems}
>
{({ onItemsRendered, ref }) => (
<List
className="List"
height={150}
itemCount={1000}
itemSize={35}
// This is outerElementType is way to pass some function down to Row
outerElementType={outerElementType}
width={300}
>
{Row}
</List>
)}
</Fragment>
);
I successfully pass 'function' and works but property not.
How to pass props down in same time with function?
This is codesandbox example:
https://codesandbox.io/s/4zqx79nww0
I have never used react-window but maybe you can do something like this:
import React, { forwardRef } from "react";
import ReactDOM from "react-dom";
import { FixedSizeList as List } from "react-window";
import "./styles.css";
const Row = props => ({ index, style }) => (
<div className={index % 2 ? "ListItemOdd" : "ListItemEven"} style={style}>
Row {index} {props.test}
</div>
);
function handleOnWheel({ deltaY }) {
// Your handler goes here ...
console.log("handleOnWheel()", deltaY);
}
const outerElementType = forwardRef((props, ref) => (
<div ref={ref} onWheel={handleOnWheel} {...props} />
));
const Example = () => (
<List
className="List"
height={150}
itemCount={1000}
itemSize={35}
outerElementType={outerElementType}
width={300}
>
{Row({ test: "test" })}
</List>
);
ReactDOM.render(<Example />, document.getElementById("root"));

Categories