Open raphaelpc opened 4 years ago
Importante: i'm using "react-input-mask": "^3.0.0-alpha.0",
If anyone faces the same problem, this was my temporary solution (until the component gets updated (IF it gets updated)...):
/*
* React currently throws a warning when using useLayoutEffect on the server.
* To get around it, we can lazily show component with useLayoutEffect.
* Ref: https://gist.github.com/gaearon/e7d97cdf38a2907924ea12e4ebdf3c85
*/
import React, { useState, useEffect } from 'react'
import ReactInputMask from "react-input-mask";
const InputMask = props => {
const [showChild, setShowChild] = useState(false);
// Wait until after client-side hydration to show
useEffect(() => {
setShowChild(true);
}, []);
if (!showChild) {
// You can show some kind of placeholder UI here
return null;
}
return (
<ReactInputMask {...props} />
)
}
export default InputMask;
In this specific case, the best approach I found (InputMask + Next JS) is to use the dynamic
import feature from Next.
Basically, just create a single component that renders the InputMask component itself:
// components/InputMask.tsx
import MaskedInput from "react-input-mask";
const InputMask: React.FC<Props> = (props) => (
<MaskedInput {...props} />
);
export default InputMask;
Then, when you want you want to use it, imports it dynamically without server-side rendering:
const CustomComponent: React.FC<Props> = (props) => {
const InputMaskNoSSR = useMemo(
() =>
dynamic(() => import("components/InputMask"), {
ssr: false,
}),
[]
)
return (<InputMaskNoSSR {...props} />)
}
Doing this, the InputMask
component will be rendered in the client only and all warnings will disappear.
Happy coding!
My workaround was to use the
import { NoSsr } from '@material-ui/core';
export const MaskedTextField = (props: Props) => {
const { name, control } = props;
return (
<NoSsr>
<Controller
name={name}
control={control}
render={({ field: { value, onChange } }) => (
<InputMask
mask="(0)999 999 99 99"
maskPlaceholder={null}
value={value}
onChange={onChange}
>
<MuiTextField variant="outlined" fullWidth {...props} />
</InputMask>
)}
/>
</NoSsr>
);
}
@redbaron76's solution worked for me!
To avoid installing Material-UI you can use this:
import { Fragment, ReactNode, useEffect, useLayoutEffect, useState } from "react";
type Props = {
children: ReactNode;
}
function NoSsr(props: Props) {
const [mountedState, setMountedState] = useState(false);
const useEnhancedEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect;
const defer = false;
useEnhancedEffect(() => {
if (!defer) {
setMountedState(true);
}
}, [defer]);
useEffect(() => {
if (defer) {
setMountedState(true);
}
}, [defer]);
// We need the Fragment here to force react-docgen to recognise NoSsr as a component.
return <Fragment>{mountedState ? props.children : undefined}</Fragment>;
}
export default NoSsr
This is my solution. I have SEO requirements, so I need some input rendered during SSR. I'm rendering my UI library (Chakra) input on SSR and I switch to react-input-mask
on the client. I made them to look visually the same.
import { Input } from '@chakra-ui/react';
import InputMask from 'react-input-mask';
// Component
const [showMask, setShowMask] = useState(false);
useEffect(() => {
setShowMask(true);
}, []);
const inputElement = showMask ? (
<InputMask
mask="99-99-9999"
maskPlaceholder="dd-mm-yyyy"
alwaysShowMask
onChange={onChange}
value={value}
/>
) : (
<Input defaultValue="dd-mm-yyyy" />
);
Hello! I'm creating an application using React 16.8.6 + NextJS 9.0.2. It has a page that contains a Form that uses the component React Input Mask. When i run the application, i get the following warning:
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. See https://fb.me/react-uselayouteffect-ssr for common fixes. in InputMask (at Form.js:348)
I did not find any reference here about that warning. Do anyone know what would be the best solution to resolve it? I tried forcing the form to render only on the client but it makes the page slow, and i dont really think that would be the best solution.
Thanks in advance!