Next.js React 앱에서 창이 정의되지 않았습니다.
Next.js 앱에서 액세스할 수 없는 것 같습니다.window
:
처리되지 않은 거부(ReferenceError): 창이 정의되지 않았습니다.
componentWillMount() {
console.log('window.innerHeight', window.innerHeight);
}
'h''s's's's's''n't't's'l't's'l's's's's'i'i'n's's's'i's's'i's's'y's's's's's's's'i's's's's's's's's's's's's's's's's's's's's'sp̶r̶o̶c̶e̶s̶s̶.̶b̶r̶o̶w̶s̶e̶r
'to' 'j'u' 'e' 'e' 'e' 'e' 'e' 'o' 'm' a n d' 'd' 'u' 'i ng' 'e' 'e' 'c' 'm' a
★★★★★★★★★★★★★★★★★.process
'노드'JS Webpack 5 Next J스스 스 스 스스무리
다시 요.window
오브젝트를 지정합니다.
if (typeof window !== "undefined") {
// Client-side-only code
}
해결책은 훅을 하여 리액트 을 대체하는 입니다.componentDidMount
:
useEffect(() => {
// Client-side-only code
})
를 「」에서 이동합니다.componentWillMount()
대상:
componentDidMount() {
console.log('window.innerHeight', window.innerHeight);
}
Next.js의 componentDidMount()
는, 「이행」이에서만 실행됩니다.window
기타 브라우저 고유의 API를 이용할 수 있습니다.Next.js Wiki에서:
next.js는 범용입니다.즉, 먼저 서버측에서 코드를 실행하고 다음으로 클라이언트측에서 코드를 실행합니다.창 개체는 클라이언트 측에서만 존재하므로 일부 React 구성 요소에서 반드시 액세스할 수 있어야 하는 경우 componentDidMount에 해당 코드를 넣어야 합니다.이 라이프 사이클 메서드는 클라이언트에서만 실행됩니다.또한 필요에 맞는 대체 유니버설 라이브러리가 없는지 확인하는 것이 좋습니다.
행으로, 「 」는 「 」componentWillMount()
React의 v17에서는 권장되지 않기 때문에 가까운 장래에 사용하는 것은 사실상 안전하지 않을 수 있습니다.
리액트 훅을 사용하면 코드를 이펙트 훅으로 이동할 수 있습니다.
import * as React from "react";
export const MyComp = () => {
React.useEffect(() => {
// window is accessible here.
console.log("window.innerHeight", window.innerHeight);
}, []);
return (<div></div>)
}
「 」의 .useEffect
는 클라이언트에서만 실행되므로 (브라우저)에 액세스 할 수 있습니다.window
.
SSR 없음
https://nextjs.org/docs/advanced-features/dynamic-import#with-no-ssr
import dynamic from 'next/dynamic'
const DynamicComponentWithNoSSR = dynamic(
() => import('../components/hello3'),
{ ssr: false }
)
function Home() {
return (
<div>
<Header />
<DynamicComponentWithNoSSR />
<p>HOME PAGE is here!</p>
</div>
)
}
export default Home
컴포넌트가 아직 마운트되어 있는 동안에는 창을 사용할 수 없기 때문에 오류가 발생.구성 요소가 마운트된 후 창 개체에 액세스할 수 있습니다.
다이나믹하게 하기 , 할 수 .window.innerHeight
★★★★★★★★★★★★★★★★★」window.innerWidth
const useDeviceSize = () => {
const [width, setWidth] = useState(0)
const [height, setHeight] = useState(0)
const handleWindowResize = () => {
setWidth(window.innerWidth);
setHeight(window.innerHeight);
}
useEffect(() => {
// component is mounted and window is available
handleWindowResize();
window.addEventListener('resize', handleWindowResize);
// unsubscribe from the event on component unmount
return () => window.removeEventListener('resize', handleWindowResize);
}, []);
return [width, height]
}
export default useDeviceSize
사용 사례:
const [width, height] = useDeviceSize();
componentWillMount()
라이프 사이클 훅은 서버측과 클라이언트측 모두에서 동작합니다. 수 있습니다.window
★★★★★★★★★★★★★★★★★」document
서비스 .
해결책 1:
componentDidMount()
또는 솔루션 2
실행만 하고 싶은 경우 다음과 같이 쓸 수 있습니다.
componentWillMount() {
if (typeof window !== 'undefined') {
console.log('window.innerHeight', window.innerHeight);
}
}
클래스 생성자에서 컴포넌트를 추가할 수 있습니다.
if (typeof window === 'undefined') {
global.window = {}
}
예:
import React, { Component } from 'react'
class MyClassName extends Component {
constructor(props){
super(props)
...
if (typeof window === 'undefined') {
global.window = {}
}
}
이렇게 하면 오류가 발생하지 않습니다(이 경우 페이지 새로고침을 클릭한 후에 오류가 발생합니다).
조금 늦었지만 다이내믹 Import를 사용하는 것도 검토해 주십시오.next
끄다SSR
그 컴포넌트에 대해서요.
동적 함수 내에서 컴포넌트의 Import를 워프한 후 반환된 값을 실제 컴포넌트로 사용할 수 있습니다.
import dynamic from 'next/dynamic'
const BoardDynamic = dynamic(() => import('../components/Board.tsx'), {
ssr: false,
})
<>
<BoardDynamic />
</>
global?.window && window.innerHeight
?.
건축하다
URL에서 해시에 접속해야 하기 때문에, 이것을 생각해냅니다.
const hash = global.window && window.location.hash;
역대 최고의 솔루션
import dynamic from 'next/dynamic';
const Chart = dynamic(()=> import('react-apexcharts'), {
ssr:false,
})
다음은 사용하기 쉬운 회피책입니다.
const runOnClient = (func: () => any) => {
if (typeof window !== "undefined") {
if (window.document.readyState == "loading") {
window.addEventListener("load", func);
} else {
func();
}
}
};
사용방법:
runOnClient(() => {
// access window as you like
})
// or async
runOnClient(async () => {
// remember to catch errors that might be raised in promises, and use the `await` keyword wherever needed
})
그냥 .typeof window !== "undefined"
창이 정의되어 있지 않은지 확인만 하면 페이지가 로 리다이렉트 되어도 동작하지 않고 로드 중에 한 번만 동작하기 때문입니다.다만, 이 회피책은, 로드중에 1 회만이 아니고, 페이지가 리다이렉트 된 경우에도 유효합니다.
next.js에서 웹 어플리케이션을 개발할 때도 같은 문제에 직면해 있었습니다.이 때문에 문제가 해결되었습니다.라이프 사이클 방식이나 리액트 훅에서는 윈도 오브젝트를 참조해야 합니다.예를 들어 redux를 사용하여 스토어 변수를 만들고 이 스토어에서는 다음과 같이 Windows 개체를 사용할 수 있습니다.
let store
useEffect(()=>{
store = createStore(rootReducers, window.__REDUX_DEVTOOLS_EXTENSION__ &&
window.__REDUX_DEVTOOLS_EXTENSION__())
}, [])
....
할 때는 to to so so so so so so so so so so so so so so so so so so so so so so so so so so so 。componentDidMount()
용액을 했습니다.if (typeof window === 'undefined') return;
커스텀 훅으로, 매우 만족하고 있습니다.은, 반응하는 있습니다.useMemo
이치노
import { useEffect, useMemo, useState } from "react";
const InitialState = Symbol("initial");
/**
*
* @param clientFactory Factory function similiar to `useMemo`. However, this function is only ever called on the client and will transform any returned promises into their resolved values.
* @param deps Factory function dependencies, just like in `useMemo`.
* @param serverFactory Factory function that may be called server side. Unlike the `clientFactory` function a resulting `Promise` will not be resolved, and will continue to be returned while the `clientFactory` is pending.
*/
export function useClientSideMemo<T = any, K = T>(
clientFactory: () => T | Promise<T>,
deps: Parameters<typeof useMemo>["1"],
serverFactory?: () => K
) {
const [memoized, setMemoized] = useState<T | typeof InitialState>(
InitialState
);
useEffect(() => {
(async () => {
setMemoized(await clientFactory());
})();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, deps);
return typeof window === "undefined" || memoized === InitialState
? serverFactory?.()
: memoized;
}
사용 예:
next.js의 SSR와 호환되지 않는 라이브러리를 동적으로 가져오기 위해 사용합니다. 왜냐하면 동적 가져오기는 컴포넌트와만 호환되기 때문입니다.
const renderer = useClientSideMemo(
async () =>
(await import("@/components/table/renderers/HighlightTextRenderer"))
.HighlightTextRendererAlias,
[],
() => "text"
);
보시는 바와 같이 폴백팩토리 콜백도 실장되어 있기 때문에 서버에서 처음 렌더링할 때도 결과를 제공할 수 있습니다. 모든 에서 이 는 반응과 하게 동작해야 .useMemo
후크. 피드백에 개방적이야.
이러한 경우 Next.js에는 동적 가져오기가 있습니다.
브라우저에서만 작동하는 라이브러리를 포함하는 모듈입니다. 동적 가져오기를 사용하는 것이 좋습니다.참조
날짜: 2021년 6월 8일
window 객체가 존재하는지 확인한 후 코드를 따릅니다.
function getSelectedAddress() {
if (typeof window === 'undefined') return;
// Some other logic
}
Next.js 버전12.1.0의 경우,process.title
있는지 browser
★★★★★★★★★★★★로node
움이이됐됐!
export default function Projects(props) {
console.log({ 'process?.title': process?.title });
return (
<div></div>
);
}
1. 단말기로부터 수신합니다.{ 'process?.title': 'node' }
2. Chrome devtool에서 복습합니다.{ 'process?.title': 'browser' }
페이지를 새로 고칠 때도 같은 문제가 발생했습니다(SSR에서 제대로 작동하지 않는 가져오기로 인해 발생).
이 문제를 해결한 것은 이 문제가 발생한 페이지로 이동하여 Import를 동적으로 강제하는 것이었습니다.
import dynamic from 'next/dynamic';
const SomeComponent = dynamic(()=>{return import('../Components/SomeComponent')}, {ssr: false});
//import SomeComponent from '../Components/SomeComponent'
컴포넌트의 원래 Import 및 Import를 코멘트 아웃하면 컴포넌트의 클라이언트 측 렌더링이 동적으로 실행됩니다.
동적 Import에 대해서는 다음 URL의 Nextjs 문서를 참조하십시오.https://nextjs.org/docs/advanced-features/dynamic-import
저는 이 해결책에 대해 여기 유튜브 비디오를 보고 알게 되었습니다.
상태 변수를 정의하고 창 이벤트 핸들을 사용하여 이와 같은 변경을 처리할 수 있습니다.
const [height, setHeight] = useState();
useEffect(() => {
if (!height) setHeight(window.innerHeight - 140);
window.addEventListener("resize", () => {
setHeight(window.innerHeight - 140);
});
}, []);
현재 경로 이름(CurrentUrl Path)을 얻기 위해 -와 같은 사용 사례에 대해 아래 코드 스니펫을 사용할 수 있습니다.
import { useRouter } from "next/router";
const navigator = useRouter()
console.log(navigator.pathname);
후크를 사용할 수 없는 경우(예를 들어 기능 구성요소):
setTimeout(() => yourFunctionWithWindow());
를 사용하면 윈도 인스턴스를 얻을 수 있습니다.로딩하는 데 시간이 좀 더 필요한 것 같아요.
저는 제가 흥미를 느낀 이 접근방식을 미래의 연구자들에게 남기고 싶습니다.커스텀 훅 useEventListener를 사용하여 많은 다른 요구에서 사용할 수 있습니다.
여기서 제안하는 것처럼 원래 게시된 내용에 약간의 변경 사항을 적용해야 합니다.
이렇게 끝납니다.
import { useRef, useEffect } from 'react'
export const useEventListener = (eventName, handler, element) => {
const savedHandler = useRef()
useEffect(() => {
savedHandler.current = handler
}, [handler])
useEffect(() => {
element = !element ? window : element
const isSupported = element && element.addEventListener
if (!isSupported) return
const eventListener = (event) => savedHandler.current(event)
element.addEventListener(eventName, eventListener)
return () => {
element.removeEventListener(eventName, eventListener)
}
}, [eventName, element])
}
NextJS 앱과 _document.js 내부에 있는 경우 다음을 사용하십시오.
<script dangerouslySetInnerHTML={{
__html: `
var innerHeight = window.innerHeight;
`
}} />
언급URL : https://stackoverflow.com/questions/55151041/window-is-not-defined-in-next-js-react-app
'programing' 카테고리의 다른 글
ANSI 컬러 기능에 대한 spring-boot 로그백을 설정하려면 어떻게 해야 합니까? (0) | 2023.04.01 |
---|---|
jQuery ajax와 ES6의 약속 (0) | 2023.04.01 |
데이터 소스를 자동 구성하지 못했습니다. 'spring.datasource.url'이 지정되지 않았습니다. (0) | 2023.04.01 |
데이터 소스를 자동 구성하지 못했습니다. 'spring.datasource.url'이 지정되지 않았습니다. (0) | 2023.04.01 |
Woocommerce - 주문 품목의 가격과 수량을 가져옵니다. (0) | 2023.04.01 |