Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Out of memory error using debug() in an Animated.FlatList with a ref #539

Closed
Paduado opened this issue Sep 8, 2020 · 10 comments
Closed

Comments

@Paduado
Copy link

Paduado commented Sep 8, 2020

Describe the bug

I'm implementing a test in a component that renders an Animated.FlatList, when I use debug the test hangs and eventually throws a JavaScript heap out of memory error.

I found out that If I remove the ref I'm passing to the Animated.FlatList everything works fine.
It also works with a regular FlatList.

Expected behavior

Test shouldn't hang and debug() output should be visible in the console.

Steps to Reproduce

Run this test:

function MyFlatList() {
  const ref = useRef();
  return (
    <Animated.FlatList
      ref={ref}
      data={[1, 2, 3]}
      renderItem={({ item }) => <Text>{item}</Text>}
    />
  );
}

test('FlatList', () => {
  const { debug } = render(<MyFlatList />);
  debug();
  expect(true).toBe(true);
});

The test will hang and throw this error:
FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory

Versions

@testing-library/react-native: 7.0.2 => 7.0.2 
react: 16.13.1 => 16.13.1 
react-native: 0.63.2 => 0.63.2 
react-test-renderer: ^16.13.1 => 16.13.1 
@louiszawadzki
Copy link

Hi, we've faced a similar issue.
It looks as if when using a ref on an Animated component, the snapshot becomes huge.

As an example, you can run:

import React, { useRef } from 'react';
import { Animated } from 'react-native';
import { render } from 'react-native-testing-library';

const Component = () => {
  const ref = useRef(null);
  return <Animated.View ref={ref} />;
};

describe('component', () => {
  it('renders', () => {
    const page = render(<Component />);
    expect(page).toMatchSnapshot();
  });
});

And see that the snaphsot is nearly 3,000 lines long.
If you use an Animated.ScrollView instead of Animated.View, the snapshot is more than 30,000 lines long!

Also this might be linked to jestjs/jest#8109

@Ziew
Copy link

Ziew commented Dec 22, 2020

Any update on that?
Workaround for me was mocking Animated.ScrollView but it's not perfect solution.

mergify bot pushed a commit to celo-org/celo-monorepo that referenced this issue Dec 22, 2020
### Description

This fixes the regression described in #6314.

The change in #6230 made the underlying problem in `AlertBanner` more prominent as it caused the top level navigator to re-render on app state change (background/foreground/inactive) and hence the `AlertBanner`.

### Other changes

Globally mock `Animated.View` and `Animated.ScrollView` to prevent out of memory error when a ref is set.
See callstack/react-native-testing-library#539

Note: This change caused the Snapshot updates, because the styles are not flattened anymore for the mocked `Animated.View`.

### Tested

- Last alert is not redisplayed when navigating to different screens.
- New alert banner with same content can still be redisplayed when dispatched (causing a state change).

### Related issues

- Fixes #6314

### Backwards compatibility

Yes
@raimonkh
Copy link

raimonkh commented Feb 2, 2021

What I did was increase the size of memory for node export NODE_OPTIONS := --max_old_space_size=8192

@pke
Copy link
Contributor

pke commented Oct 3, 2021

Just encountered this too in the form of jestjs/jest#8109

Sad, that there does not seem to be a workaround for that. Increasing the memory of the node process is not really a valid solution. The ref problem has its roots somewhere else.

edit: Seems my problem goes away when I am using Pressable instead of TouchableOpacity to put my ref on.

@scrungrth
Copy link

scrungrth commented Nov 13, 2021

adding this worked for my test:

import { Animated, View } from 'react-native';

...

it('should work', () => {
    Object.defineProperty(Animated, 'View', {
      get value() {
        return View;
      },
    });
    ...
});

@sparachi
Copy link

On the lines of @pke comments, re-adjusting the ref worked for me too. jestjs/jest#10577 (comment)

@blimmer
Copy link

blimmer commented Nov 17, 2021

Depending on the Node version you're using, the OOM might be compounded by this issue: jestjs/jest#11956

@mdjastrzebski
Copy link
Member

Seems like the root issue is related to the actual size of component tree generated by using Animated wrappers. If so then the you can work around the issue by:

  1. including memory allocated to jest instance using approach described by @raimonkh
  2. mocking Animated implementation as described by @scrungrth, preferably using jest features instead of Object.defineProperty

@redreceipt
Copy link

redreceipt commented Mar 11, 2023

Any update on that?
Workaround for me was mocking Animated.ScrollView but it's not perfect solution.

How did you mock Animated.ScrollView? This is the solution I'd like to go with

@AugustinLF
Copy link
Collaborator

Something like that should work

jest.mock('react-native', () => {
  const rn = jest.requireActual('react-native'
  return {
    ...rn,
    Animated: {
      ...rn.Animated,
      View: rn.View,
    }
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests