Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to fix the "Warning: useLayoutEffect does nothing on the server"?

Heres the full error:

Warning: useLayoutEffect does nothing on the server, because its effect cannot be encoded into the server renderer's output format. This will lead to a mismatch between the initial, non-hydrated UI and the intended UI. To avoid this, useLayoutEffect should only be used in components that render exclusively on the client

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

I get it every time I run my test. Heres my test

/* 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)     })   }) }) 

I believe it has something to do with the material-ui component. I've looked into it, theres a similar question on here that says the issue has to do with a dependency that my project does not have. So I think it has to do with the material-ui component using useEffectLayout and the testing env doesnt like that for some reason. Im running my test with yarn and jest yarn test to run the test suite.

like image 228
jkeary Avatar asked Sep 23 '19 22:09

jkeary


People also ask

Does useLayoutEffect run on the server?

Option 1: Convert to useEffect Like useLayoutEffect , it won't run on the server, but it also won't warn.

What is useIsomorphicLayoutEffect?

useIsomorphicLayoutEffect() The signature is identical to useEffect, but it fires synchronously after all DOM mutations. That means this hook is a browser hook. But React code could be generated from the server without the Window API.

When should I use Layouteffect?

useLayoutEffect. The signature is identical to useEffect , but it fires synchronously after all DOM mutations. Use this to read layout from the DOM and synchronously re-render. Updates scheduled inside useLayoutEffect will be flushed synchronously, before the browser has a chance to paint.

Does useEffect run server side?

useEffect doesn't run on server-side render (SSR): useEffect runs after the render.


1 Answers

adding

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

to my frontend/src/setupTests.js test file is a way to suppress the jest warning. Ultimately, this looks to be an issue with Material-UI components having issues with Jest.

like image 188
jkeary Avatar answered Sep 27 '22 17:09

jkeary