programing

"Warning: useLayoutEffect does nothing on server?"를 수정하는 방법

stoneblock 2023. 2. 23. 22:00

"Warning: useLayoutEffect does nothing on server?"를 수정하는 방법

다음은 완전한 오류입니다.

경고: useLayoutEffect는 서버 렌더러의 출력 형식으로 인코딩할 수 없으므로 서버에서 아무 작업도 수행하지 않습니다.이로 인해 초기 유압식 UI와 의도된 UI가 일치하지 않게 됩니다.이를 방지하려면 useLayoutEffect를 클라이언트 전용으로 렌더링하는 컴포넌트에서만 사용해야 합니다.

      in ForwardRef(ButtonBase)
      in WithStyles(ForwardRef(ButtonBase))
      in ForwardRef(Button)
      in WithStyles(ForwardRef(Button))
      in form
      in div

검사를 할 때마다 나와요.내 시험이다

/* eslint-disable quotes */
import React from "react"
import { shallow, configure } from "enzyme"
import LoginForm from "../src/components/LoginForm"
import Button from "@material-ui/core/Button"
import Adapter from "enzyme-adapter-react-16"
import { render, fireEvent, cleanup } from "@testing-library/react"

configure({ adapter: new Adapter() })

describe("<LoginForm />", () => {
  let wrapper
  let usernameInput
  let passwordInput
  let signInButton

  // Create initial props that get passed into the component
  const initialProps = {
    location: {
      state: {
        from: {
          pathname: "/",
        },
      },
    },
  }

  // Unit testing
  describe("Unit tests", () => {
    // what to do before each test
    beforeEach(() => {
      // Render the login form component, pass in props. (Shallow method renders the component without its children, good for unit tests.)
      wrapper = shallow(<LoginForm {...initialProps} />)
      usernameInput = wrapper.find("#username")
      passwordInput = wrapper.find("#password")
      signInButton = wrapper.find(Button)
    })

    // what to do after each test
    afterEach(() => {
      jest.clearAllMocks()
    })

    // UI Integrity test
    it("should match the snapshot", () => {
      // snapshots are text references of the html of the rendered component.
      expect(wrapper.html()).toMatchSnapshot()
    })

    it("should have a username inputs", () => {
      expect(usernameInput.length).toEqual(1)
    })

    it("should have the expected props on the username field", () => {
      expect(usernameInput.props()).toEqual({
        id: "username",
        name: "username",
        value: "",
        type: "username",
        onChange: expect.any(Function),
        required: true,
      })
    })

    it("should have a password field", () => {
      expect(passwordInput.length).toEqual(1)
    })

    it("should have the expected props on the password field", () => {
      expect(passwordInput.props()).toEqual({
        id: "password",
        name: "password",
        value: "",
        type: "password",
        onChange: expect.any(Function),
        required: true,
      })
    })

    it("should have a submit button", () => {
      expect(signInButton.length).toEqual(1)
    })

    it("should have the expected props on the button", () => {
      expect(signInButton.props()).toEqual({
        type: "button",
        variant: "contained",
        style: expect.objectContaining({
          marginTop: "10px",
        }),
        onClick: expect.any(Function),
        children: "Sign In",
      })
    })
  })

  // Integrations Testing
  describe("Integrations tests", () => {
    beforeEach(() => {
      // Render the login form component, pass in props. (render method renders the component with its children, good for integrations tests, uses react-test-library.)
      const { getByLabelText, getByText } = render(
        <LoginForm {...initialProps} />
      )
      usernameInput = getByLabelText(/Username/i)
      passwordInput = getByLabelText(/Password/i)
      signInButton = getByText("Sign In")
    })

    afterEach(cleanup)

    it("Username text change in onChange event", () => {
      expect(usernameInput.value).toBe("")

      fireEvent.change(usernameInput, { target: { value: "James" } })

      expect(usernameInput.value).toBe("James")
    })

    it("Password text change in onChange event", () => {
      expect(passwordInput.value).toBe("")

      fireEvent.change(passwordInput, { target: { value: "mypassword" } })

      expect(passwordInput.value).toBe("mypassword")
    })

    it("Test button submit", () => {
      const mockLogin = jest.fn()

      const button = shallow(<Button onClick={mockLogin} />)

      button.simulate("click")

      expect(mockLogin.mock.calls.length).toEqual(1)
    })
  })
})

material-ui 성분과 관련이 있는 것 같아요.제가 조사해 봤는데, 이 문제 역시 제 프로젝트에 없는 의존성과 관련이 있다는 비슷한 질문입니다.그래서 제 생각엔 material-ui component와 관련이 있는 것 같아요.useEffectLayout테스트 환경은 어떤 이유에서인지 그것을 좋아하지 않는다.나는 실과 농담으로 내 시험을 치르고 있다.yarn test테스트 스위트를 실행합니다.

추가

import React from "react" 
React.useLayoutEffect = React.useEffect 

frontend/src/setupTests.js 테스트 파일은 농담 경고를 억제하는 방법입니다.궁극적으로, 이것은 Jest와 문제가 있는 Material-UI 컴포넌트의 문제로 보입니다.

조금 더 깔끔한 해결책은 다음과 같이 jajest mock을 사용하는 것입니다.

jest.mock('react', () => ({
  ...jest.requireActual('react'),
  useLayoutEffect: jest.requireActual('react').useEffect,
}));

useLayoutEffect를 다음과 같이 사용할 수 있는지 확인해야 합니다.

import React, {useEffect, useLayoutEffect} from 'react';

const canUseDOM = typeof window !== 'undefined';
const useIsomorphicLayoutEffect = canUseDOM ? useLayoutEffect : useEffect;

그 후,useLayoutEffect을 사용하다useIsomorphicLayoutEffect

스타트업 파일의 선두에 다음의 if 스테이트먼트(예:index.js)를 추가하는 것으로, 이 문제를 해결할 수 있습니다.

if (typeof document === 'undefined') {
  React.useLayoutEffect = React.useEffect;
}

이를 통해 SSR는React.useEffect대신React.useLayoutEffect왜냐면document는 서버측에서 정의되어 있지 않습니다.

언급URL : https://stackoverflow.com/questions/58070996/how-to-fix-the-warning-uselayouteffect-does-nothing-on-the-server