带有反应测试库的状态更新警告

时间:2021-05-27 15:40:54

标签: reactjs react-testing-library

我有一个加载器组件,它从一个类组件重构为一个功能组件。代码似乎完全相同,但出于某种原因,在类组件版本中,我在功能版本中没有收到任何警告。 这个错误通常需要在测试中做一些工作,但在这种情况下,我认为组件是有错误的那个。即使我更改了测试(我认为这很容易完成),我对使用此 Loader 的其他组件还有很多其他测试,这意味着我应该更改其中的每一个。

警告信息 Warning: An update to Loader inside a test was not wrapped in act(...).

我会留下两个版本

旧版本 - 类组件(无警告)

import React from 'react'

class Loader extends React.Component {
  state = {
    isLoaderVisible: this.props.delay <= 0,
    isLoading: true,
    error: null,
    response: null
  }

  componentDidMount() {
    if (!this.state.isLoaderVisible) {
      this.loaderVisibilityTimeout = setTimeout(
        () => this.setState({ isLoaderVisible: true }),
        this.props.delay
      )
    }
    this.props
      .fetch()
      .then(response => this.setState({ response, isLoading: false }))
      .catch(error => this.setState({ error, isLoading: false }))
  }

  componentWillUnmount() {
    clearTimeout(this.loaderVisibilityTimeout)
  }

  loaderVisibilityTimeout = null

  render() {
    const { renderLoader, renderSuccess, renderError } = this.props
    const { isLoaderVisible, isLoading, response, error } = this.state

    if (isLoading) {
      if (isLoaderVisible) {
        return renderLoader()
      }
      return null
    }

    if (error) {
      return renderError(error)
    }

    return renderSuccess(response)
  }
}

Loader.defaultProps = {
  delay: 0,
  renderLoader: () => <div>Loading</div>,
  renderError: error => (
    <div data-testid="error">
      <h1>Something went wrong</h1>
      <p>{error.message}</p>
    </div>
  )
}

新版本 - 功能组件(有警告)

import React, { useEffect, useRef, useState } from 'react'
import PropTypes from 'prop-types'
import Placeholder, { ELayoutType } from './Placeholder'

let counter = 1

const Loader = ({ delay, renderLoader, renderSuccess, renderError, fetch }) => {
  const [state, setState] = useState({
    isLoaderVisible: delay <= 0,
    isLoading: true,
    error: null,
    response: null
  })

  const loaderVisibilityTimeout = useRef(null)
  const { isLoaderVisible, isLoading, response, error } = state

  useEffect(() => {
    if (!isLoaderVisible) {
      loaderVisibilityTimeout.current = setTimeout(
        () => setState({ ...state, isLoaderVisible: true }),
        delay
      )
    }
    fetch()
      .then(res => setState({ ...state, response: res, isLoading: false }))
      .catch(err => setState({ ...state, error: err, isLoading: false }))

    return () => clearTimeout(loaderVisibilityTimeout.current)
  }, [])

  console.log(counter)
  counter++

  if (isLoading) {
    if (isLoaderVisible) {
      return renderLoader()
    }
    return null
  }

  if (error) {
    return renderError(error)
  }

  return renderSuccess(response)
}

Loader.defaultProps = {
  delay: 0,
  renderLoader: () => <div>Loading</div>,
  renderError: error => (
    <div data-testid="error">
      <h1>Something went wrong</h1>
      <p>{error.message}</p>
    </div>
  )
}

0 个答案:

没有答案