![](/img/trans.png)
[英]How to fix "Warning: useLayoutEffect does nothing on the server" while using Material UI and reactDOMServer?
[英]How to fix the "Warning: useLayoutEffect does nothing on the server"?
這是完整的錯誤:
警告:useLayoutEffect 在服務器上什么都不做,因為它的效果不能被編碼成服務器渲染器的 output 格式。 這將導致初始的非水合 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 組件有關。 我已經調查過了, 這里有一個類似的問題,說這個問題與我的項目沒有的依賴關系有關。 所以我認為這與使用useEffectLayout
的 material-ui 組件有關,並且由於某種原因,測試環境不喜歡這樣。 我用 yarn 和 jest yarn test
運行我的測試來運行測試套件。
添加
import React from "react"
React.useLayoutEffect = React.useEffect
到我的前端/src/setupTests.js 測試文件是一種抑制開玩笑警告的方法。 最終,這似乎是 Material-UI 組件與 Jest 存在問題的問題。
更清潔的解決方案可能是像這樣使用 jest 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
在服務器端未定義。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.