notes

#ssr

๐Ÿซ  Hydration Mismatch ๐Ÿซ  (1)2023. 6. 2.

์ด๋Ÿฐ ์ €๋Ÿฐ ์ด์œ ๋กœ ํด๋ผ์ด์–ธํŠธ ์ƒํƒœ๋ฅผ localStorage ๋“ฑ์— persist ํ•˜๊ณ  ์žˆ์„ ๊ฒฝ์šฐ server/client mismatch๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ๋ฐ–์— ์—†๋Š”๋ฐ ๊ทธ๋ž˜์„œ ์„œ๋ฒ„์—์„œ ํ”„๋ฆฌ๋ Œ๋”๊ฐ€ ์•ˆ๋˜๊ฒŒ ํ•˜๋ ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์€ ๋‚œ๋ฆฌ ๋ฒ•์„์ด ํ•„์š”.

  1. useState + useEffect
    function Comp() {
      const storeState = useStoreState()
            ^^^^^^^^^^ 1) ์š”๊ฑธ ๊ทธ๋ƒฅ ์“ฐ๋ฉด ๐Ÿ’ฃ ์ธ ๊ฒฝ์šฐ,
    
      const [state, setState] = React.useState()
      React.useEffect(()=>{
        setState(storeState)
      },[])               // 2) ์ด๋Ÿฐ ๋‚œ๋ฆฌ ๋ฒ•์„ ํ›„์—
    
      return <div>{state}</div> // 3) ์ด๋Ÿฌ๋ฉด ํ†ต๊ณผ
    function Comp() {
      const storeState = useStoreState()
            ^^^^^^^^^^ 1) ์š”๊ฑธ ๊ทธ๋ƒฅ ์“ฐ๋ฉด ๐Ÿ’ฃ ์ธ ๊ฒฝ์šฐ,
    
      const [state, setState] = React.useState()
      React.useEffect(()=>{
        setState(storeState)
      },[])               // 2) ์ด๋Ÿฐ ๋‚œ๋ฆฌ ๋ฒ•์„ ํ›„์—
    
      return <div>{state}</div> // 3) ์ด๋Ÿฌ๋ฉด ํ†ต๊ณผ
  2. useMounted + return null
    // 0) ์ผ๋‹จ ์ด๋Ÿฐ ๋‚œ๋ฆฌ ๋ฒ•์„์„ ๋งŒ๋“ค์–ด๋‘๊ณ 
    const useMounted = () => {
      const [m, sM] = React.useState(false)
      //     ^^^^^ ๊ท€์ฐฎ์•„์„œ ๋Œ€์ถฉ ์”€
      React.useEffect(()=>{
        sM(true)
      }, [])
      return m
    }
    // 0) ์ผ๋‹จ ์ด๋Ÿฐ ๋‚œ๋ฆฌ ๋ฒ•์„์„ ๋งŒ๋“ค์–ด๋‘๊ณ 
    const useMounted = () => {
      const [m, sM] = React.useState(false)
      //     ^^^^^ ๊ท€์ฐฎ์•„์„œ ๋Œ€์ถฉ ์”€
      React.useEffect(()=>{
        sM(true)
      }, [])
      return m
    }
    function Comp() {
      const storeState = useStoreState()
            ^^^^^^^^^^ 1) ์š”๊ฑธ ๊ทธ๋ƒฅ ์“ฐ๋ฉด ๐Ÿ’ฃ ์ธ ๊ฒฝ์šฐ,
    
      const mounted = useMounted()
      if (!mounted) return null  // 2) ์ด๋Ÿฌ๊ณ  ๋‚˜์„œ
    
      return <div>{storeState}</div> // 3) ์ด๋Ÿฌ๋ฉด ํ†ต๊ณผ
    function Comp() {
      const storeState = useStoreState()
            ^^^^^^^^^^ 1) ์š”๊ฑธ ๊ทธ๋ƒฅ ์“ฐ๋ฉด ๐Ÿ’ฃ ์ธ ๊ฒฝ์šฐ,
    
      const mounted = useMounted()
      if (!mounted) return null  // 2) ์ด๋Ÿฌ๊ณ  ๋‚˜์„œ
    
      return <div>{storeState}</div> // 3) ์ด๋Ÿฌ๋ฉด ํ†ต๊ณผ
  3. next/dynamic + { ssr: false } โ˜œ ์ด๊ฒŒ ๊ธฐ๋ถ„์ด ์ œ์ผ ๋œ ๋‚˜์œ๋“ฏ
    const Comp = dynamic(() => import('path/to/comp'), { ssr: false }); // ์ ค ๊ฐ„๋‹จ?
    const Comp = dynamic(() => import('path/to/comp'), { ssr: false }); // ์ ค ๊ฐ„๋‹จ?
    ํ•˜์ง€๋งŒ ์บ์น˜๊ฐ€ ํ•˜๋‚˜ ์žˆ๋Š”๋ฐ, Comp ๋Š” ๋ฌด์กฐ๊ฑด export default ์—ฌ์•ผ ํ•จ.
    const Comp = dynamic(() => import('path/to/comp').then(mod => mod.Comp), { ssr: false })
                                                        // ^^^^^^^^^^^^^^^ ์ด๋Ÿฌ๋ฉด ๐Ÿ’ฃ
    const Comp = dynamic(() => import('path/to/comp').then(mod => mod.Comp), { ssr: false })
                                                        // ^^^^^^^^^^^^^^^ ์ด๋Ÿฌ๋ฉด ๐Ÿ’ฃ
    ๋Œ€์‹  loading์œผ๋กœ ์„œ์ŠคํŽœ์Šค ๊ฐ„์ง€๋ฅผ ๋‚ผ ์ˆ˜ ์žˆ์Œ(...)
    const Comp = dynamic(() => import('path/to/comp'), { ssr: false, loading: () => <Sekeleton /> }); // ์ด ๊ฐ€๋Šฅ
    const Comp = dynamic(() => import('path/to/comp'), { ssr: false, loading: () => <Sekeleton /> }); // ์ด ๊ฐ€๋Šฅ
    ๋ฌผ๋ก  next ํ•œ์ •์ด์ง€๋งŒ์š”...

์ด๊ฑฐ ๋‹ค ๋ณ„๋ฃจ๊ณ ... ๋กœ ์‹œ์ž‘ํ•˜๋Š” ๊ธ€์„ ํ•œ์ฐธ ์“ฐ๊ณ  ์žˆ์—ˆ๋Š”๋ฐ ๋ธŒ๋ผ์šฐ์ € ๊บผ์ ธ์„œ ๋‚ ์•„๊ฐ...

Tags