聞きたいこと
webブラウザのウィンドウサイズによってヘッダーナビゲーションを動的に変更したいと思っています。
具体的にはモバイル用のウィンドウサイズとPC用のウィンドウサイズでヘッダーナビゲーションを変更しようと思っているのですが、
ウィンドウサイズをモバイル用サイズにした状態でブラウザをリロードすると、下のワーニングメッセージが表示されてしまいます。
react-dom.development.js?61bb:88 Warning: Expected server HTML to contain a matching <button> in <header>
ソースコード
- _app.tsx
TypeScript
1import React from 'react'; 2import { AppProps } from 'next/app'; 3import { RecoilRoot } from 'recoil'; 4import '@@/styles/globals.css'; 5 6import HeaderContainer from '@/components/containers/HeaderContainer'; 7 8const App = ({ Component, pageProps }: AppProps): any => { 9 return ( 10 <RecoilRoot> 11 {/* ここでHeaderContainerを呼び出し */} 12 <HeaderContainer /> 13 <Component {...pageProps} /> 14 </RecoilRoot> 15 ); 16}; 17 18export default App; 19
- HeaderContainer.tsx
TypeScript
1import * as React from 'react'; 2 3import Header from '@/components/gui/groups/Header'; 4import { useWindowDimensions } from '@/hooks'; 5 6const HeaderContainer: React.FC = () => { 7 const { width, height } = useWindowDimensions(); 8 // useWindowDimensions() カスタムコンポーネントから取得したwidth, heightをHeaderに引き渡し 9 return ( 10 <Header width={width} /> 11 ) 12} 13 14export default HeaderContainer; 15
- useWindowDimensions.ts
TypeScript
1import * as React from 'react'; 2import { atom, useRecoilState } from 'recoil'; 3 4const getWindowDimensions = () => { 5 let width: number; 6 let height: number; 7 if (process.browser) { 8 width = window.innerWidth; 9 height = window.innerHeight; 10 } 11 return { 12 width, 13 height 14 }; 15} 16 17export const windowDimensionsState = atom({ 18 key: 'windowDimensionsState', 19 default: getWindowDimensions() 20}) 21 22const useWindowDimensions = () => { 23 const [windowDimensions, setWindowDimensions] = useRecoilState(windowDimensionsState); 24 React.useEffect(() => { 25 if (process.browser) { 26 const onResize = () => { 27 setWindowDimensions(getWindowDimensions); 28 } 29 window.addEventListener('resize', onResize); 30 return () => { 31 window.removeEventListener('resize', onResize) 32 } 33 } 34 }, []) 35 // stateで管理されたwidth, heightをreturnする 36 return windowDimensions; 37} 38 39export { useWindowDimensions } 40
- Header.tsx
TypeScript
1import * as React from 'react'; 2import Link from 'next/link'; 3import styled from 'styled-components'; 4 5import { PRIMARY, TABLET_MEDIA, MOBILE_MEDIA } from '@/utils/constants'; 6import { Burger } from '@/components/gui/parts/Burger'; 7 8interface Props { 9 width: number 10} 11 12const Header: React.FC<Props> = (props) => { 13 const { width } = props; 14 15 if (width < 600) { 16 // モバイル用のHeader 17 return ( 18 <Wrapper> 19 <Burger /> 20 </Wrapper> 21 ) 22 } else { 23 // PC用のHeader 24 return ( 25 <Wrapper> 26 <Nav> 27 <Link href="/top"> 28 <StyledA>Top</StyledA> 29 </Link> 30 </Nav> 31 </Wrapper> 32 ); 33 } 34}; 35 36export default Header; 37 38const Wrapper = styled.header` 39 background-color: ${PRIMARY}; 40 position: fixed; 41 z-index: 999; 42 height: 55px; 43 top: 0; 44 left: 0; 45 right: 0; 46`; 47 48const Nav = styled.nav` 49 max-width: 800px; 50 box-sizing: border-box; 51 margin: 0 auto; 52 padding: 15px 5px; 53 ${TABLET_MEDIA} { 54 padding: 15px 30px; 55 } 56 ${MOBILE_MEDIA} { 57 padding: 15px; 58 } 59`; 60 61const StyledA = styled.a` 62 color: rgba(255, 255, 255, 0.8); 63 transition: color 0.15s ease; 64 line-height: 24px; 65 display: inline-block; 66 vertical-align: middle; 67 font-weight: 300; 68 letter-spacing: 0.075em; 69 margin-right: 1.8em; 70 cursor: pointer; 71 &:hover { 72 color: #fff; 73 } 74`; 75
- Burger.tsx
TypeScript
1import * as React from 'react'; 2import styled from 'styled-components'; 3 4const Burger = () => { 5 return ( 6 <Button> 7 <div /> 8 <div /> 9 <div /> 10 </Button> 11 ) 12} 13 14export { Burger }; 15 16const Button = styled.button` 17 position: absolute; 18 top: 5%; 19 left: 2rem; 20 display: flex; 21 flex-direction: column; 22 justify-content: space-around; 23 width: 2rem; 24 height: 2rem; 25 background: transparent; 26 border: none; 27 cursor: pointer; 28 padding: 0; 29 z-index: 10; 30 31 &:focus { 32 outline: none; 33 } 34 35 div { 36 width: 2rem; 37 height: 0.25rem; 38 border-radius: 10px; 39 transition: all 0.3s linear; 40 position: relative; 41 transform-origin: 1px; 42 } 43`; 44
あなたの回答
tips
プレビュー