[Next] Next에서의 alert, window, document , localStorage 사용 가능할까?

손종일·2020년 12월 19일
4

Next.js

목록 보기
5/5
post-thumbnail
post-custom-banner

Next에서의 alert, window, document 사용 가능할까?

= 우리가 기존에 사용하던 대로 사용한다면 SSR에서는 해당 객체나 메소드에 접근하지 못하고 에러가 출력됩니다.
CSR에서는 접근이 가능하지만, SSR에서는 접근하지 못하고 에러가 출력됩니다.

1. SSR에서는 사용하지 못하기 때문에 useEffect를 사용하여 CSR에서 사용하자!

useEffect(() => {},[]) 는 렌더링이 되고 난 후 실행되기 때문에 useEffect는 서버사이드에서는 실행되지 않는 CSR 전용 이벤트라고 생각할 수 있습니다. 그렇기 때문에 useEffect를 사용하여 SSR이 완료 된 후 동작하게 한다면 에러가 출력되지 않습니다. 의존성 배열의 값을 잘 활용하여 useEffect를 사용한다면 localStorage, alert() 등을 사용할 수 있습니다.

아래의 예제는 todo-list를 만들어 localStorage에 저장하고 불러오는 컴포넌트를 작성한 내용입니다.
따라 치면서 한번 다같이 이해해 봅시다!

------------------------------------------------------------------/pages/api/double.tsx
import React, { useCallback, useEffect, useState } from 'react';
import styled from 'styled-components';

const AddBtn = styled.button`
  background-color:skyblue;
`;

const RemoveBtn = styled.button`
  background-color:red;
`;

function TodoList  () {
  const [list, setList] = useState([])
  const [text, setText] = useState('')
  //window 객체는 CSR에서는 접근 가능하지만, SSR에서는 접근 못하고 에러가 출력된다.
  // window is not defined가 출력되면 SSR에서의 window 객체이기 때문이라고 추측 가능
  // alert, document 다 SSR에서는 접근할 수 없다.
  // console.log(window)
  // console.log(alert(' '))
  // console.log(document)

  // 또한 서버에서는 LocalStorage를 읽지 못한다.
  // 그렇기때문에 useEffect를 사용해서 페이지가 렌더 된 후 사용해야 한다.
  // useEffect -> 컴디마, 컴디업을 비교해서 다루는데
  // 즉 useEffect는 서버사이드에서는 실행되지 않는 CSR 전용 이벤트가 된다.

  useEffect(() => {
    console.log('123')
    console.log(localStorage)
    const result = localStorage.getItem('todo-list')
    console.log(JSON.parse(result))
    setList(JSON.parse(result))
  }, [])

  const addItem = useCallback(() => {
    const items = [...list,
      {
      id: (new Date().getTime()).toString(),
      text
    }]
    setList(items)
    localStorage.setItem('todo-list', JSON.stringify(items))
  },[list, text])

  const removeItem = useCallback((id) => {
    const filterList = list.filter((el) => {
      return el.id !== id && el
    })
    setList(filterList)
    localStorage.setItem('todo-list', JSON.stringify(filterList))
  },[list])

  return (
    <>
      <h1>TODO List</h1>
      <div>
        할일 내용 <input type="text" value={text} onChange={(e) => setText(e.target.value)}/> 
        <AddBtn onClick={addItem}>추가</AddBtn>
        <ul>
          <li>할일내용<RemoveBtn>삭제</RemoveBtn></li>
          {list.map((el) => {
            return (
              <li key={el.id}>{el.text}<RemoveBtn onClick={() => removeItem(el.id)}>삭제</RemoveBtn></li>
            )
          })}
        </ul>
      </div>
    </>
  )
}

export default TodoList
profile
Allday
post-custom-banner

0개의 댓글