代码之家  ›  专栏  ›  技术社区  ›  Lin Du Correcter

RTL不会抛出无效的挂钩调用警告

  •  0
  • Lin Du Correcter  · 技术社区  · 3 年前

    来自 Rules Of Hooks ,我们知道React钩子不能在条件内调用。我有一个定制的反作用挂钩 useRemoteData 我把它放在 if(visible) return null 陈述所以它打破了钩子的规则。

    我希望RTL应该抛出无效的钩子调用警告。但事实并非如此。两个测试用例在没有任何警告的情况下通过。

    Eslint给出正确的警告信息:

    React Hook“useRemoteData”是有条件调用的。在每个组件渲染中,必须以完全相同的顺序调用React Hooks。你是不是在提前回来后不小心叫了React Hook?esintract钩子/钩子规则

    fn.tsx :

    import React from 'react';
    import { useEffect, useState } from 'react';
    import { api } from './api';
    
    const useRemoteData = () => {
      const [state, setState] = useState('');
      useEffect(() => {
        api.ajax().then(() => setState('fake data'));
      }, []);
      return state;
    };
    
    interface TempCompProps {
      visible?: boolean;
    }
    export function TempComp({ visible = true }: TempCompProps) {
      if (!visible) return null;
      useRemoteData();
      return <div>TempComp</div>;
    }
    

    fn.test.tsx :

    import { render, screen, waitFor } from '@testing-library/react';
    import React from 'react';
    import { TempComp } from './fn';
    
    describe('TempComp', () => {
      test('should render component', async () => {
        render(<TempComp visible />);
        expect(await screen.findByText(/TempComp/)).toBeTruthy();
      });
      test('should not render component', () => {
        render(<TempComp visible={false} />);
        waitFor(() => {
          expect(screen.queryByText(/TempComp/)).toBeFalsy();
        });
      });
    });
    

    测试结果:

      console.log
        simulate HTTP request
    
          at Object.<anonymous> (issues/component-visible-control/api.ts:3:13)
    
     PASS  issues/component-visible-control/fn.test.tsx
      TempComp
        ✓ should render component (52 ms)
        ✓ should not render component (3 ms)
    
    Test Suites: 1 passed, 1 total
    Tests:       2 passed, 2 total
    Snapshots:   0 total
    Time:        3.426 s, estimated 5 s
    

    软件包版本:

    "@testing-library/react": "^12.1.2",
    "react": "^16.14.0",
    "react-dom": "^16.14.0",
    "jest": "^27.3.0",
    
    0 回复  |  直到 3 年前
        1
  •  1
  •   Sebastian    3 年前

    如果并且仅当钩子调用的数量在组件的生命周期内保持不变,这对React来说实际上是很好的。由于一个测试只呈现零个钩子,而另一个测试则只呈现一个钩子,因此不会引发任何错误。

    但是,一旦用零个钩子和一个钩子渲染组件,就会开始看到崩溃:

    const {rerender} = render(<TempComp visible={false} />);
    rerender(<TempComp visible={false} />);
    

    如果有道理,请告诉我