question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Laggy scroll experience due to image fetch

See original GitHub issue

Hello,

I have a weird issue related to refreshing images. This library made a scrolling much nicer however I cannot push production until I fix the following issue. Spending couple of hours everyday to fix with no luck so I hope one of you can help me out. 😃

I have a listing with the following setup:

Item.js // 100% wide, 140px tall blocks with image background and text on it CachedImage.js // storing images on the device using react-native-fs

I tried several things to make the scrolling smooth but it’s not there yet. Implemented shouldComponentUpdate methods as well to reduce unnecessary rendering.

  1. If I remove the images the scrolling is perfect
  2. If I remove CachedImage and replace with normal Image component sending the actual CDN URL the scrolling is perfect, although there is a flash when refreshing the images (this is not ideal as there are a lot of images in my app and would eat the mobile bandwidth in a second)
  3. If I increase renderAheadOffset to a very high number it works perfectly, because there is no rerender

I do think the issue is with the async getCachedPath() function, which returns the cached path based on the url.

CachedImage.js


constructor(props) {
	super(props);

	this.fetchImage = this.fetchImage.bind(this);

	this.state = {
		imagePath: null,
	};
}

componentDidMount() {
	this.fetchImage(this.props);
}

componentWillReceiveProps(nextProps) {
	if (this.props.source && nextProps.source &&
		!_.isEqual(this.props.source, nextProps.source)
	) {
		this.fetchImage(nextProps);
	}
}

shouldComponentUpdate(nextProps, nextState) {
	return this.state.imagePath !== nextState.imagePath;
}

async fetchImage(props) {
	const imagePath = await getCachedPath(props.source.uri);
	this.setState({ imagePath });
}

render() {
	const { imagePath } = this.state;
	return <Image source={{ uri: imagePath }} />;
}

getCachedPath (when I’m testing images are cached already so the only async command is await RNFS.exists(path) by that point)

const getCachedPath = async (uri: string): Promise<{ path: string }> => {

	// check if url is valid
	if (uri.indexOf('http://') === -1 && uri.indexOf('https://') === -1) {
		return uri;
	}

	const origFileName = uri.substring(uri.lastIndexOf('/'), uri.indexOf('?') === -1 ? uri.length : uri.indexOf('?'));
	const ext = origFileName.indexOf('.') === -1 ? '.jpg' : origFileName.substring(origFileName.lastIndexOf('.'));
	const pathPrefix = Platform.OS === 'android' ? 'file:' : '';
	const fileName = `${SHA1(uri)}${ext}`;
	const path = `${BASE_DIR}${fileName}`;
	const returnPath = `${pathPrefix}${path}`;

	const isExist = await RNFS.exists(path);

	// check if file exists
	if (isExist) {
		return returnPath;
	}

	// TODO: maybe we don't have to do this every time
	try {
		await RNFS.mkdir(BASE_DIR, { NSURLIsExcludedFromBackupKey: true });
	} catch (err) {
		fn.notify('CacheManager:CreateDir', err);
	}

	const downloadOptions = {
		fromUrl: uri,
		toFile: path,
	};

	try {
		const fileRes = await RNFS.downloadFile(downloadOptions).promise;

		if (fileRes.statusCode === 200) {
			return returnPath;
		}
	} catch (err) {
		console.log('err', err
	}
};

RecyclerListView.js

constructor(props) {
	super(props);

	this.dataProvider = new DataProvider((r1, r2) => r1 !== r2);

	this.layoutProvider = new LayoutProvider(
		index => 'Event',
		(type, dim) => {
			dim.width = width;
			dim.height = 140;
		}
	);

	this.state = {
		dataProvider: this.dataProvider.cloneWithRows(this.props.data),
	};
}

render() {
	return (
		<RecyclerListView
			dataProvider={this.state.dataProvider}
			layoutProvider={this.layoutProvider}
			rowRenderer={this.rowRenderer}
		/>
	);
}

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:5

github_iconTop GitHub Comments

2reactions
markhomokicommented, Jan 5, 2019

I never had that issue before, however my pictures are always the same width and height. Also for the images, I use them as a backgroud so they use position: absolute. I’m not sure if changing the styling will fix your issue. If you share a bit of your code, it might help one of us spot the issue.

0reactions
nehacs09commented, Jan 5, 2019

@markhomoki - I am facing issue using react-native-fast-image library with recyclerlistview, sometimes my images are not renering with correct aspect ratio while doing scroll (with recycling). Can you please help if you have faced this issue too

Read more comments on GitHub >

github_iconTop Results From Across the Web

UICollectionView laggy/choppy scrolling from ... - Stack Overflow
The problem is that the cells with the NSAttributedString cause the CollectionView scroll to be very laggy and choppy. The specific thing ...
Read more >
Scrolling Lag Test --> Found the perfect example, need testers ...
With the reddit app, it *seems* that the images are loaded dynamically as you scroll and the images are needed to be displayed...
Read more >
Major scrolling lag on page full of scaled down high resolution ...
we noticed that issue happen when browser resolution get higher than 1280p and we scale image ( not tested background-image but a real...
Read more >
HTML images lag when scrolling over them - SitePoint
I have 9 images on a page. 3 images per row. After all the images have been downloaded, I start scrolling from the...
Read more >
How Images are Slowing Down Page Load Time ... - Snipcart
Decide on an optimal width and height for image display on different end-user devices like desktop, laptop, tablet, smartphone. Do not use one ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found