You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native导航测试中Animated(View)未包裹act警告的解决方法

问题背景

下面的测试代码实现了从Source页面导航到Target页面:

import 'react-native-gesture-handler/jestSetup';

import React, {Component, useEffect} from 'react';
import {NavigationContainer} from '@react-navigation/native';
import {createStackNavigator} from '@react-navigation/stack';
import {render} from '@testing-library/react-native';

const SourceFunc = ({navigation}) => {
  useEffect(() => navigation.navigate('Target'), [navigation]);
};

class SourceClass extends Component {
  componentDidMount() {
    this.props.navigation.navigate('Target');
  }

  render() {}
}

const Target = () => {}; 

for (let i = 0; i < 5; i++) {
  it('', async () => {
    const Stack = createStackNavigator();
    await render(
      <NavigationContainer>
        <Stack.Navigator>
          <Stack.Screen name="Source" component={SourceFunc} />
          <Stack.Screen name="Target" component={Target} />
        </Stack.Navigator>
      </NavigationContainer>,
    );  
  }); 
}

for (let i = 0; i < 5; i++) {
  it('', async () => {
    const Stack = createStackNavigator();
    await render(
      <NavigationContainer>
        <Stack.Navigator>
          <Stack.Screen name="Source" component={SourceClass} />
          <Stack.Screen name="Target" component={Target} />
        </Stack.Navigator>
      </NavigationContainer>,
    );  
  }); 
}

测试全部通过,但弹出大量如下警告:

Warning: An update to Animated(View) inside a test was not wrapped in act(...).

When testing, code that causes React state updates should be wrapped into act(...):

act(() => {
  /* fire events that update state */
});
/* assert on the output */

This ensures that you're testing the behavior the user would see in the browser. Learn more at https://reactjs.org/link/wrap-tests-with-act

虽然已经使用await render,但不清楚警告中提到的Animated(View)更新来源。

问题

如何在React Native测试中执行导航操作,同时避免触发该警告?

补充说明
  • 单次测试不会触发警告(因此用多轮测试来复现问题)
  • 若单测执行时间小于约130ms,也不会触发警告
完整复现步骤
pushd $(mktemp -d)
npx react-native init test
pushd test
yarn add @react-navigation/native @react-navigation/stack react-native-gesture-handler react-native-safe-area-context
yarn add --dev @testing-library/react-native
patch -p1 <<EOF
--- a/jest.config.js
+++ b/jest.config.js
@@ -1,3 +1,4 @@
 module.exports = {
   preset: 'react-native',
+  transformIgnorePatterns: [],
 };
EOF
# 添加test.js文件
npx jest test.js
解决方案

这个警告源于React Navigation的页面切换动画在测试结束后仍在执行状态更新,且这些更新未被act()包裹。可以通过以下几种方式解决:

1. 禁用导航动画

在测试时给Stack.Navigator添加screenOptions={{ animationEnabled: false }},直接关闭页面切换动画,从根源避免Animated组件的状态更新:

await render(
  <NavigationContainer>
    <Stack.Navigator screenOptions={{ animationEnabled: false }}>
      <Stack.Screen name="Source" component={SourceFunc} />
      <Stack.Screen name="Target" component={Target} />
    </Stack.Navigator>
  </NavigationContainer>,
);

2. 用waitFor等待所有更新完成

在render之后调用waitFor,确保所有异步状态更新都执行完毕,让这些操作自动被act()包裹:

import {render, waitFor} from '@testing-library/react-native';

// ...测试代码
await render(/* 组件内容 */);
await waitFor(() => {}); // 等待所有pending的状态更新完成

3. 模拟Animated模块

在jest配置中模拟Animated模块,跳过真实的动画逻辑:
在jest.setup.js中添加:

jest.mock('react-native/Libraries/Animated/NativeAnimatedHelper');

或者直接在测试文件顶部添加模拟:

jest.mock('react-native', () => {
  const originalRN = jest.requireActual('react-native');
  return {
    ...originalRN,
    Animated: {
      ...originalRN.Animated,
      timing: jest.fn(() => ({ start: jest.fn() })),
      spring: jest.fn(() => ({ start: jest.fn() })),
    },
  };
});

4. 添加短暂延迟(不推荐)

如果以上方法都不适用,可以在测试末尾添加一个短暂延迟,让动画更新完成:

await new Promise(resolve => setTimeout(resolve, 150));

内容的提问来源于stack exchange,提问作者msbit

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 22:08:29