1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【React】Styled Componentsをfunction App()の内側に記載するとエラーになる

1
Posted at

こんにちは。

学習目的の個人開発でReactのStyled Componentsを用いてtextareaの入力を実装していた際、突如エラーが発生して入力欄が見えなくなる事象が発生しました。

今回はその際に起きたエラーと解決策を備忘録代わりに書いていきます。

①当記事は学習のアウトプットを目的としたものです。予めご了承ください。
②記事内の和訳はGoogle翻訳を利用しています。

発生したエラーと事象

Styled Componentsでスタイリングしたテキストエリアに文字を入力したところ、以下のようなエラーが発生しました。

Uncaught Error: Rendered fewer hooks than expected. This may be caused by an accidental early return statement.
(訳:捕捉されないエラー: 予想よりも少ない数のフックがレンダリングされました。これは、意図せず早期に return 文が実行されたことが原因である可能性があります。)

また、ページにアクセスした際にも以下のような警告が出ていました。

The component styled.div with the id of "(自動生成されたクラス名)" has been created dynamically.
You may see this warning because you've called styled inside another component.
To resolve this only create new StyledComponents outside of any render method and function component.
(訳:IDが「(自動生成されたクラス名)」のコンポーネント styled.div は動的に作成されました。
この警告は、別のコンポーネント内で styled を呼び出した場合に表示されることがあります。
この問題を解決するには、レンダリングメソッドや関数コンポーネントの外部で新しい StyledComponent を作成してください。)

エラーが発生した際のコード

下記のようにApp関数の内側でStyled Componentsのコンポーネントを定義していました。

sample.tsx
import { useState } from 'react'
import './App.css'
import styled from 'styled-components'

function App() {
    const Wrapper = styled.div`
        (wrapperコンポーネント内で適用させたいスタイル)
    `

    const ReactTextarea = styled.textarea`
        (ReactTextareaコンポーネント内で適用させたいスタイル)
    `

    const MarkdownArea = styled.div`
        (MarkdownAreaコンポーネント内で適用させたいスタイル)
    `

    const [markdownText, setMarkdownText] = useState("");

    const inputText = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
        const targetValue = e.currentTarget.value;
        setMarkdownText(targetValue);
    }
    
    return (
    <>
      <Wrapper>
        <ReactTextarea name="textarea" onChange={inputText}></ReactTextarea>
        <Markdown 
          remarkPlugins={[remarkBreaks, remarkGfm]} 
          components={{
            p: ({ children }) => <p style={{ marginBottom: "1em" }}{children</p>,
          }}
          >{markdownText}</Markdown>
      </Wrapper>
    </>
  )  
}

理由と対策例

上記のようなコードはStyled Components公式でも非推奨とされている記述例でした。

It is important to define your styled components outside of the render method, otherwise it will be recreated on every single render pass. Defining a styled component within the render method will thwart caching and drastically slow down rendering speed, and should be avoided.
(訳:Styled Componentsはrenderメソッドの外側で定義することが重要です。そうしないと、レンダリングのたびに再生成されてしまうからです。renderメソッド内でStyled Componentsを定義すると、キャッシュが機能しなくなり、レンダリング速度が著しく低下するため、避けるべきです。)

公式ドキュメントでは以下のようなコードが推奨例として提示されています。

const StyledWrapper = styled.div`
  /* ... */
`;

const Wrapper = ({ message }) => {
  return <StyledWrapper>{message}</StyledWrapper>;
};

実際に前述のエラーが出ていたコードに関してもfunction App()の外側にStyled Componentsのコンポーネントを記述したところエラーが解消されました。

最後に

ここまで読んでいただきありがとうございます。
Styled Componentsは配置する場所が重要でした。

予想外のエラーについては公式ドキュメントに解説が記載されていることが多いので、今後はエラーが出たら公式ドキュメントを見てみる習慣をより意識しようと思います。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?