preguntas-entrevista-react - 就職⚛️の面接のための典型的な反応の質問

(Preguntas típicas sobre React para entrevistas de trabajo ⚛️)

Created at: 2022-08-28 19:07:28
Language: JavaScript
License: MIT

Reactの面接の質問

ゼロからエキスパートへ。スペイン語🇪🇸の詳細な回答付き

プロジェクトが気に入ったら、そのままにしてください。

Twitchプログラミングストリーム:twitch.tv/midudev
Discord開発コミュニティ:discord.gg/midudev


インデックス


ビギナー

反応とは何ですか?

Reactは、ユーザーインターフェイスを構築するためのオープンソースのJavaScriptライブラリです。これはUIのコンポーネント化に基づいています:インターフェイスは、独自の状態を含む独立したコンポーネントに分割されます。コンポーネントの状態が変更されると、React はインターフェイスを再レンダリングします。

これにより、Reactは、インターフェイスをより小さく再利用可能な部分に分割できるため、複雑なインターフェイスを構築するための非常に便利なツールになります。

これは、Facebookで働いていたソフトウェアエンジニアであり、複雑なユーザーインターフェイスを作成する方法を簡素化したいと考えていたジョーダンウォークによって2011年に作成されました。

非常に人気のあるライブラリであり、フェイスブック、ネットフリックス、Airbnb、ツイッター、インスタグラムなどの多くの企業で使用されています。

興味のあるリンク:

目次に戻る


Reactの主な機能は何ですか?

Reactの主な機能は次のとおりです。

  • コンポーネント: React は UI のコンポーネント化に基づいています。インターフェイスは、独自の状態を含む独立したコンポーネントに分割されます。コンポーネントの状態が変更されると、React はインターフェイスを再レンダリングします。

  • 仮想 DOM: React は仮想 DOM を使用してコンポーネントをレンダリングします。仮想 DOM は、実際の DOM のメモリ内表現です。コンポーネントの状態が変更されると、React はインターフェイスを再レンダリングします。実際のDOMを変更する代わりに、Reactは仮想DOMを変更し、仮想DOMを実際のDOMと比較します。このようにして、Reactは実際のDOMにどのような変更を適用する必要があるかを認識します。

  • 宣言型:Reactは宣言型であり、タスクの実行方法を指定するのではなく、何を実行するかを指定します。これにより、コードの理解と保守が容易になります。

  • 単方向: React は一方向であり、データは一方向にのみ流れます。データは親コンポーネントから子コンポーネントに流れます。

  • ユニバーサル: React はクライアントとサーバーの両方で実行できます。また、React Nativeを使用して、AndroidおよびiOS用のネイティブアプリを作成することもできます。

目次に戻る


宣言型とはどういう意味ですか?

指示に基づいてインターフェイスをレンダリングする方法は説明しません。何をレンダリングするかを教え、Reactがレンダリングを処理します。

宣言型と命令型の例:

// Declarativo
const element = <h1>Hello, world</h1>

// Imperativo
const element = document.createElement('h1')
element.innerHTML = 'Hello, world'

目次に戻る


コンポーネントとは

コンポーネントは、インターフェイスの一部をレンダリングするコードです。コンポーネントは、パラメーター化、再利用でき、独自の状態を含めることができます。

React では、コンポーネントは関数またはクラスを使用して作成されます。

目次に戻る


JSXとは何ですか?

ReactはJSXを使用して何をレンダリングするかを宣言します。JSXは、視覚的にHTMLに近いコードを記述できるJavaScript拡張機能であり、コードの読みやすさが向上し、理解しやすくなります。

JSXを使用しない場合は、次のようにインターフェイス要素を手動で作成する必要があります。

React.createElement

import { createElement } from 'react'

function Hello () { // un componente es una función! 👀
  return React.createElement(
    'h1', // elemento a renderizar
     null, // atributos del elemento
    'Hola Mundo 👋🌍!' // contenido del elemento
  )
}

これは非常に面倒で読めません。そのため、ReactはJSXを使用して何をレンダリングするかを宣言します。そのため、JSXを次のように使用します。

function Hello () {
  return <h1>Hola Mundo 👋🌍!</h1>
}

どちらのコードも同等です。

目次に戻る


JSXはどのように変換されますか?

JSXは、トランスパイラーまたはコンパイラを使用して、ブラウザーで互換性のあるJavaScriptコードに変換されます。今日最も有名なのはBabelで、変換をサポートするために多くのプラグインを使用していますが、SWCなどの他のプラグインもあります。

JSXがどのようにバベルコードの遊び場に変わるかを見ることができます。

トランスパイラーが不要な特別な場合があります。たとえば、DenoはJSX構文をネイティブにサポートしており、互換性を持たせるためにコードを変換する必要はありません。

目次に戻る


Reactのコンポーネントと要素の違いは何ですか?

コンポーネントは、小道具を受け取り、要素を返す関数またはクラスです。 要素は、DOM ノードまたは React コンポーネントのインスタンスを表すオブジェクトです。

// Elemento que representa un nodo del DOM
{
  type: 'button',
  props: {
    className: 'button button-blue',
    children: {
      type: 'b',
      props: {
        children: 'OK!'
      }
    }
  }
}

// Elemento que representa una instancia de un componente
{
  type: Button,
  props: {
    color: 'blue',
    children: 'OK!'
  }
}

目次に戻る


Reactでコンポーネントを作成するにはどうすればよいですか?

React のコンポーネントは、React 要素を返す関数またはクラスです。現在、最も推奨されるのは関数を使用することです。

function HelloWorld() {
  return <h1>Hello World!</h1>
}

ただし、クラスを使用してReactコンポーネントを作成することもできます。

import { Component } from 'react'

class HelloWorld extends Component {
  render() {
    return <h1>Hello World!</h1>
  }
}

重要なことは、関数またはクラスの名前が大文字で始まることです。これは、ReactがコンポーネントとHTML要素を区別できるようにするために必要です。

目次に戻る


Reactの小道具とは何ですか?

小道具はコンポーネントのプロパティです。これは、あるコンポーネントから別のコンポーネントに渡されるデータです。たとえば、ボタンを表示するコンポーネントがある場合、それに prop を渡して、ボタンにそのテキストを表示させることができます。

Button
text

function Button(props) {
  return <button>{props.text}</button>
}

コンポーネントは汎用ボタンであり、prop はボタンに表示されるテキストであることを理解できました。そのため、再利用可能なコンポーネントを作成しています。

Button
text

また、JSX内でJavaScript式を使用する場合は、それらをでラップする必要があり、この場合はオブジェクト、そうしないとJSXはそれをプレーンテキストと見なします。

{}
props

これを使用するには、コンポーネントの名前を示し、必要な小道具を渡します。

<Button text="Haz clic aquí" />
<Button text="Seguir a @midudev" />

小道具は、関数と同じようにコンポーネントをパラメータ化する方法です。他のコンポーネントも含め、あらゆるタイプのデータをコンポーネントに渡すことができます。

目次に戻る


Reactの小道具は何ですか、そしてそれは何のためにありますか?
children

prop は、コンポーネントに渡される特別な prop です。これは、コンポーネントがラップする要素を含むオブジェクトです。

children

たとえば、タイトルとコンテンツを含むカードを表示するコンポーネントがある場合、prop を使用してコンテンツを表示できます。

Card
children

function Card(props) {
  return (
    <div className="card">
      <h2>{props.title}</h2>
      <div>{props.children}</div>
    </div>
  )
}

そして、次のように使用できます。

<Card title="Título de la tarjeta">
  <p>Contenido de la tarjeta</p>
</Card>

この場合、prop には要素 .

children
<p>Contenido de la tarjeta</p>

Reactで再利用可能なコンポーネントを作成するには、propの使用方法を知り、知ることが非常に重要です。

children

目次に戻る


小道具と状態の違いは何ですか?

Props は、親コンポーネントから子コンポーネントに引数として渡されるオブジェクトです。これらは不変であり、子コンポーネントから変更することはできません。

状態は、コンポーネント内で定義される値です。その値は不変です(直接変更することはできません)が、Reactがコンポーネントを再レンダリングするために新しい状態値を設定できます。

したがって、小道具状態の両方がコンポーネントのレンダリングに影響しますが、それらの管理は異なります。

目次に戻る


状態は小道具の値で初期化できますか?あなたがそれをするとどうなりますか、そして何を考慮に入れるべきですか?

はい、小道具の値で状態を初期化できます。ただし、小道具が変更されても、ステータスは自動的に更新されないことに注意してください。これは、コンポーネントが最初にマウントされたときに状態が一度初期化されるためです。

たとえば、機能コンポーネントの場合:

const Counter = () => {
  const [count, setCount] = useState(0)

  return (
    <div>
      <Count count={count} />
      <button onClick={() => setCount(count + 1)}>Aumentar</button>
    </div>
  )
}

const Count = ({ count }) => {
  const [number, setNumber] = useState(count)

  return <p>{number}</p>
}

この場合、コンポーネントはその状態を prop の値で初期化します。ただし、propの値を変更しても、ステータスは自動的に更新されません。したがって、クリックすると、画面に常に数字の0が表示されます。

Count
count
count

この例では、コンポーネントで prop を使用するだけで、常に再レンダリングされます。

count
Count

コンポーネントの状態をできるだけ避け、可能な限り、小道具から表示される値を計算することをお勧めします。

小道具で状態を初期化する必要がある場合は、小道具に接頭辞を追加して、それが状態の初期値であることを示すことをお勧めします。

initial

const Input = ({ initialValue }) => {
  const [value, setValue] = useState(initialValue)

  return (
    <input
      value={value}
      onChange={e => setValue(e.target.value)}
    />
  )
}

小道具がステータスを更新すると考えるのは非常によくある間違いなので、それを覚えておいてください。

目次に戻る


Reactの条件付きレンダリングとは何ですか?

条件付きレンダリングは、条件に応じて1つのコンポーネントまたは別のコンポーネントを表示する方法です。

Reactで条件付きレンダリングを行うには、三項演算子を使用します。

function Button({ text }) {
  return text
    ? <button>{text}</button>
    : null
}

この場合、prop が存在する場合は、ボタンがレンダリングされます。存在しない場合は、何もレンダリングされません。

text

演算子 を使用した条件付きレンダリングの実装を見つけるのが一般的です。

&&

function List({ listArray }) {
  return listArray?.length && listArray.map(item=>item)
}

それは理にかなっているようです...が正(ゼロより大きい)の場合、マップを描画します。!いやそうではありません! ゼロの場合は、ブラウザで0が描画されるため、注意してください。

length
length

三項演算子を用いることが好ましい。ケントC.ドッズはそれについて話している興味深い記事を持っています。JSXでは&&ではなく三項を使用する

目次に戻る


ReactのコンポーネントにCSSクラスをどのように適用できますか、なぜそれを使用できないのですか?
class

ReactのコンポーネントにCSSクラスを適用するには、 prop を使用します。

className

function Button({ text }) {
  return (
    <button className="button">
      {text}
    </button>
  )
}

それが呼ばれる理由は、それがJavaScriptの予約語だからです。そのため、JSXでは、CSSクラスを適用するためにそれを使用する必要があります。

className
class
className

目次に戻る


Reactのコンポーネントにオンラインスタイルを適用するにはどうすればよいですか?

ReactのコンポーネントにインラインCSSスタイルを適用するには、小道具を使用します。HTMLで行う方法の違いは、Reactではスタイルがテキスト文字列ではなくオブジェクトとして渡されることです(これは、二重括弧でより明確に確認できます。

style

function Button({ text }) {
  return (
    <button style={{ color: 'red', borderRadius: '2px' }}>
      {text}
    </button>
  )
}

CSS プロパティ名もキャメルケースであることに注意してください。

目次に戻る


Reactでコンポーネントのスタイルを条件付きで設定するにはどうすればよいですか?

Reactでコンポーネントを条件付きでスタイル設定するには、小道具と三項演算子を使用します。

style

function Button({ text, primary }) {
  return (
    <button style={{ color: primary ? 'red' : 'blue' }}>
      {text}
    </button>
  )
}

前のケースでは、小道具が の場合、ボタンの色は赤になります。そうでない場合は、青色になります。

primary
true

クラスを使用して同じメカニズムに従うこともできます。この場合、三項演算子を使用して、クラスを追加するかどうかを決定します。

function Button({ text, primary }) {
  return (
    <button className={primary ? 'button-primary' : ''}>
      {text}
    </button>
  )
}

次のようなライブラリを使用することもできます。

classnames

import classnames from 'classnames'

function Button({ text, primary }) {
  return (
    <button className={classnames('button', { primary })}>
      {text}
    </button>
  )
}

この場合、prop が の場合、クラスがボタンに追加されます。そうでない場合は、追加されません。一方、クラスは常に追加されます。

primary
true
primary
button

目次に戻る


Reactのリストレンダリングとは何ですか?

リストレンダリングは、要素の配列を反復処理し、各要素のReact要素をレンダリングする方法です。

Reactでリストをレンダリングするには、配列メソッドを使用します。

map

function List({ items }) {
  return (
    <ul>
      {items.map(item => (
        <li key={item.id}>{item.name}</li>
      ))}
    </ul>
  )
}

この場合、項目のリストは を使用してレンダリングされます。コンポーネントは、 型のオブジェクトの配列である prop を受け取ります。コンポーネントは、配列内の要素ごとに 1 つの要素をレンダリングします。

List
List
items
[{id:1, name: "John", id:1, name: "Doe"}]
List
li

要素には、各要素の一意の識別子である小道具があります。これは、Reactがリスト内の各アイテムを識別して効率的に更新できるようにするために必要です。これに関するより詳細な説明を以下に示します。

li
key

目次に戻る


Reactにコメントを書くにはどうすればよいですか?

コンポーネントのレンダリングの外部でコメントを書き込む場合は、JavaScript のコメント構文をシームレスに使用できます。

function Button({ text }) {
  // Esto es un comentario
  /* Esto es un comentario
  de varias líneas */

  return (
    <button>
      {text}
    </button>
  )
}

コンポーネントのレンダリング内でコメントを書き込む場合は、コメントを中括弧で囲み、常にブロックコメント構文を使用する必要があります。

function Button({ text }) {
  return (
    <button>
      {/* Esto es un comentario en el render */}
      {text}
    </button>
  )
}

目次に戻る


Reactのコンポーネントにイベントを追加するにはどうすればよいですか?

Reactのコンポーネントにイベントを追加するには、camelCaseのネイティブブラウザイベント構文と名前を使用します。

on

function Button({ text, onClick }) {
  return (
    <button onClick={onClick}>
      {text}
    </button>
  )
}

この場合、コンポーネントは関数である prop を受け取ります。ユーザーがボタンをクリックすると、関数が実行されます。

Button
onClick
onClick

目次に戻る


Reactでイベントを処理する関数にパラメータを渡すにはどうすればよいですか?

Reactでイベントを処理する関数にパラメータを渡すには、匿名関数を使用できます。

function Button({ id, text, onClick }) {
  return (
    <button onClick={() => onClick(id)}>
      {text}
    </button>
  )
}

ユーザーがボタンをクリックすると、prop の値をパラメーターとして渡すことで関数が実行されます。

onClick
id

prop の値を渡すことで関数を実行する関数を作成することもできます。

onClick
id

function Button({ id, text, onClick }) {
  const handleClick = (event) => { // handleClick recibe el evento original
    onClick(id)
  }

  return (
    <button onClick={handleClick}>
      {text}
    </button>
  )
}

目次に戻る


反応のステータスとは何ですか?

状態は、時間の経過と共に変化する可能性のあるデータを含むオブジェクトです。React では、状態はインターフェイスへの変更を制御するために使用されます。

概念を理解するために、ルームスイッチについて考えてください。これらのスイッチには通常、オンとオフの2つの状態があります。スイッチを入れて装着するとライトが点灯し、ライトを点灯させると消灯します。

on
off

これと同じ概念をユーザー インターフェイスに適用できます。たとえば、Facebook の [いいね] ボタンには、ユーザーが「いいね!」した時と「いいね!」しなかったときのステータスが表示されます。

meGusta
true
false

状態にブール値を含めることができるだけでなく、オブジェクト、配列、数値などを持つこともできます。

たとえば、カウンタを表示するコンポーネントがある場合、ステータスを使用してカウンタの値を制御できます。

Counter

Reactでステータスを作成するには、フックを使用します。

useState

import { useState } from 'react'

function Counter() {
  const [count, setCount] = useState(0)

  return (
    <div>
      <p>Contador: {count}</p>
      <button onClick={() => setCount(count + 1)}>Aumentar</button>
    </div>
  )
}

フックを使用すると、次の 2 つの位置のいずれかが返されます。

useState
array

  1. 状態の値。
  2. ステータスを変更する機能です。

分解は通常、読み取りを容易にし、数行のコードを節約するために使用されます。一方、データをパラメータとして渡すことで、その初期状態を示しています。

useState

クラスコンポーネントを使用すると、状態の作成は次のようになります。

import { Component } from 'react'

class Counter extends Component {
  constructor(props) {
    super(props)
    this.state = { count: 0 }
  }

  render() {
    return (
      <div>
        <p>Contador: {this.state.count}</p>
        <button onClick={() => this.setState({ count: this.state.count + 1 })}>
          Aumentar
        </button>
      </div>
    )
  }
}

目次に戻る


フックとは何ですか?

フックは、関数で作成されたコンポーネントに状態やその他のReact機能を持たせることを可能にするReact APIです。

以前はこれは不可能であり、ライブラリのすべての可能性にアクセスできるようにコンポーネントを作成する必要がありました。

class

フックはフックであり、正確には、機能コンポーネントをReactが提供するすべての機能にフックできるということです。

目次に戻る


フックは何をしますか?
useState

フックは状態変数を作成するために使用され、その値が動的であり、時間の経過とともに変化する可能性があり、使用されているコンポーネントの再レンダリングが必要であることを意味します。

useState

パラメータを受け取る:

  • 状態変数の初期値。

次の 2 つの変数を持つ配列を返します。

  • まず、値を含む変数があります
  • 次の変数はset関数であり、状態の新しい値を必要とし、これは前述の変数の値を変更します
  • この関数は、状態自体の現在の値をパラメータとして提供することに注意してください。旧:
    setIsOpen(isOpen => !isOpen)

この例では、の値が 0 で初期化され、button イベントの関数で値が変更されるたびにレンダリングされる方法を示します。

count
setCount
onClick

import { useState } from 'react'

function Counter() {
  const [count, setCount] = useState(0)

  return (
    <>
      <p>Contador: {count}</p>
      <button onClick={() => setCount(count => count + 1)}>Aumentar</button>
    </>
  )
}

目次に戻る


「ステータスを上げる」という表現はどういう意味ですか?

複数のコンポーネントが状態の同じデータを共有する必要がある場合は、その共有状態を最も近い共通の祖先に昇格させることをお勧めします。

要するにあの。2 つの子コンポーネントが親の同じデータを共有する場合は、子のローカル状態を維持するのではなく、状態を親に移動します。

それを理解するには、例を挙げて見るのが最善です。ウィッシュリストがあり、ギフトを追加して、リストにあるギフトの合計を表示できるようにしたいとします。

import { useState } from 'react'

export default function App () {
  return (
    <>
      <h1>Lista de regalos</h1>
      <GiftList />
      <TotalGifts />
    </>
  )
}

function GiftList () {
  const [gifts, setGifts] = useState([])

  const addGift = () => {
    const newGift = prompt('¿Qué regalo quieres añadir?')
    setGifts([...gifts, newGift])
  }

  return (
    <>
      <h2>Regalos</h2>
      <ul>
        {gifts.map(gift => (
          <li key={gift}>{gift}</li>
        ))}
      </ul>
      <button onClick={addGift}>Añadir regalo</button>
    </>
  )
}

function TotalGifts () {
  const [totalGifts, setTotalGifts] = useState(0)

  return (
    <>
      <h2>Total de regalos</h2>
      <p>{totalGifts}</p>
    </>
  )
}

ギフトを追加するたびにギフトの合計を更新したい場合はどうなりますか?ご覧のとおり、の状態はコンポーネント内にあり、コンポーネント内にないため、不可能です。また、からステータスにアクセスできないため、ギフトを追加したときのステータスを更新することはできません。

totalGifts
TotalGifts
GiftList
GiftList
TotalGifts
totalGifts

のステータスを親コンポーネントにアップロードする必要があり、ギフトの数を小道具としてコンポーネントに渡します。

gifts
App
TotalGifts

import { useState } from 'react'

export default function App () {
  const [gifts, setGifts] = useState([])

  const addGift = () => {
    const newGift = prompt('¿Qué regalo quieres añadir?')
    setGifts([...gifts, newGift])
  }

  return (
    <>
      <h1>Lista de regalos</h1>
      <GiftList gifts={gifts} addGift={addGift} />
      <TotalGifts totalGifts={gifts.length} />
    </>
  )
}

function GiftList ({ gifts, addGift }) {
  return (
    <>
      <h2>Regalos</h2>
      <ul>
        {gifts.map(gift => (
          <li key={gift}>{gift}</li>
        ))}
      </ul>
      <button onClick={addGift}>Añadir regalo</button>
    </>
  )
}

function TotalGifts ({ totalGifts }) {
  return (
    <>
      <h2>Total de regalos</h2>
      <p>{totalGifts}</p>
    </>
  )
}

これで、私たちがしたことは国家を高めることです。コンポーネントからコンポーネントに移動しました。これで、ギフトをコンポーネントにpropsとして渡し、ステータスを更新する方法もpropとしてコンポーネントに渡しました。

GiftList
App
GiftList
TotalGifts

目次に戻る


フックは何をしますか?
useEffect

フックは、コンポーネントがレンダリングされるとき、またはエフェクトの依存関係が変更されたときにコードを実行するために使用されます。

useEffect

次の 2 つのパラメーターを受け取ります。

  • 依存関係を変更するとき、またはコンポーネントをレンダリングするときに実行する関数。
  • 依存関係の配列。依存関係の値を変更すると、関数が実行されます。

この例では、コンポーネントをロードするとき、および の値を変更するたびに、コンソールにメッセージを表示します。

count

import { useEffect, useState } from 'react'

function Counter() {
  const [count, setCount] = useState(0)

  useEffect(() => {
    console.log('El contador se ha actualizado')
  }, [count])

  return (
    <>
      <p>Contador: {count}</p>
      <button onClick={() => setCount(count + 1)}>Aumentar</button>
    </>
  )
}

目次に戻る


フックの使用例を解説
useEffect

フックは、次のようなさまざまな方法で使用できます。

useEffect

  • コンポーネントがレンダリングされたとき、エフェクトの依存関係が変更されたとき、またはコンポーネントがマウント解除されたときにコードを実行します。
  • そのため、コンポーネントをマウントするだけなので、依存関係が変更されたときにAPIを呼び出すと便利です。
  • Googleアナリティクスなどのイベントを追跡して、ユーザーがアクセスしたページを把握します。
  • フォームを検証して、ステータスが変更されるたびにUIを更新し、エラーの場所を表示できるようにすることができます。
  • ユーザーがウィンドウのサイズを変更したことを知るイベントなどのブラウザイベントをサブスクライブできます。
    resize

目次に戻る


でイベントを購読する方法
useEffect

その中で、ユーザーがウィンドウのサイズを変更したことを知るイベントなどのブラウザイベントをサブスクライブできます。メモリリークを回避するために、コンポーネントが分解されたときにサブスクライブを解除することが重要です。これを行うには、コンポーネントが逆アセンブルされたときに実行される関数を返す必要があります。

useEffect
resize
useEffect

import { useEffect } from 'react'

function Window() {
  useEffect(() => {
    const handleResize = () => {
      console.log('La ventana se ha redimensionado')
    }

    window.addEventListener('resize', handleResize)

    return () => {
      window.removeEventListener('resize', handleResize)
    }
  }, [])

  return (
    <p>Abre la consola y redimensiona la ventana</p>
  )
}

目次に戻る


フックは何をしますか?
useId

useId
は、HTML タグ属性に渡すことができる一意の識別子を生成するためのフックであり、アクセシビリティに特に役立ちます。

コンポーネントの最上位レベルで呼び出して、一意の ID を生成します。

useId

import { useId } from 'react'
function PasswordField() {
  const passwordHintId = useId()
  // ...

次に、生成された ID をさまざまな属性に渡します。

<>
  <input type="password" aria-describedby={passwordHintId} />
  <p id={passwordHintId}>
</>

タグを使用すると、2つのタグが相互に関連していることを指定することができ、画面に数回表示されても生成されたIDが衝突しないuseIdを使用して一意のIDを生成できます。

aria-describedby
PasswordField

完全な例は次のようになります。

import { useId } from 'react'

function PasswordField() {
  const passwordHintId = useId()

  return (
    <>
      <label>
        Password:
        <input
          type="password"
          aria-describedby={passwordHintId}
        />
      </label>
      <p id={passwordHintId}>
        El password debe ser de 18 letras y contener caracteres especiales
      </p>
    </>
  )
}

export default function App() {
  return (
    <>
      <h2>Choose password</h2>
      <PasswordField />
      <h2>Confirm password</h2>
      <PasswordField />
    </>
  )
}

ご覧のとおり、コンポーネントを2回使用しています。たとえば、IDを手元に置いた場合、IDは一意ではなく、複製されます。そのため、を使用してIDを自動的に生成することが重要です。

App
password
useId

目次に戻る


コンポーネントがマウントされたときにコードを実行するにはどうすればよいですか?

コンポーネントがフックを使用してマウントされると、依存関係を渡さずにコードを実行できます。この場合、最初のパラメータとして渡された関数は、コンポーネントがマウントされたときに実行されます。

useEffect

import { useEffect } from 'react'

function Component() {
  useEffect(() => {
    console.log('El componente se ha montado')
  }, [])

  return (
    <p>Abre la consola y re-dimensiona la ventana</p>
  )
}

目次に戻る


反応のフラグメントとは何ですか?

フラグメントは、Reactではコンポーネント内の複数の要素を返すことができず、1つのルート要素のみを返すことができないため、DOMに余分な要素を追加せずに要素をグループ化する方法です。

Reactでフラグメントを作成するには、次のコンポーネントを使用します。

Fragment

import { Fragment } from 'react'

function App() {
  return (
    <Fragment>
      <h1>Titulo</h1>
      <p>Párrafo</p>
    </Fragment>
  )
}

略語構文を使用することもできます。

function App() {
  return (
    <>
      <h1>Titulo</h1>
      <p>Párrafo</p>
    </>
  )
}

目次に戻る


なぜdivの代わりにフラグメントを使用するのですか?

複数の要素をラップするときに1つではなくFragmentを使用することが推奨される理由は次のとおりです。

div

  • それらはDOMに余分な要素を追加しますが、フラグメントは追加しません。これにより、HTML 要素の数と DOM の深さが小さくなります。
    div
  • フラグメントでラップされた要素は、親要素の flex または CSS グリッドプロパティの影響を直接受けます。これを使用すると、要素の配置に問題がある可能性があります。
    div
  • フラグメントは、レンダリングする必要がないため、フラグメントよりも高速です。
    div
  • CSSはデフォルトで適用されます(適用時に周囲のものがブロックのように動作します)が、フラグメントはデフォルトのスタイルを適用しません。
    div
    div
    display: block

目次に戻る


複合コンポーネントパターンとは何ですか?

これは、単一の目標を持つ親コンポーネントの作成に基づくコンポーネントデザインパターンであり、スムーズにレンダリングするために必要なプロパティを子に提供します。

新しいコンポーネントを構築するときに宣言構造を可能にし、その単純さと清潔さのためにコードを読むのにも役立ちます。

この設計の例としては、子要素をレンダリングするリストがあります。

<List>
  <ListItem>Cat</ListItem>
  <ListItem>Dog</ListItem>
</List>
const List = ({ children, ...props }) => (
  <ul {...props} >
    {children}
  </ul>
);

const ListItem = ({ children, ...props }) => {

  return (
    <li {...props}>
      {children}
    </li>
  );
};

export { List, ListItem };

これは簡単な例ですが、コンポーネントは必要に応じて複雑にすることができ、親と子の両方が独自の状態を持つことができます。

興味のあるリンク:

目次に戻る


Reactプロジェクトを最初から初期化するにはどうすればよいですか?

Reactプロジェクトを最初から初期化する方法はいくつかあります。最も人気のあるものは次のとおりです。

npm create vite@latest my-app -- --template react
npx create-react-app my-app

今日最も人気があり推奨されるオプションはViteです。ソースnpmトレンド

フレームワークの使用、最も人気のあるものは次のとおりです。

npx create-next-app@latest my-app
npm init gatsby

今日最も人気があり、推奨されるオプションはNextjsです。ソースnpmトレンド

それぞれがWebアプリケーションパッケージャーです。プロジェクトの依存関係を解決し、変更ごとに自動的に更新される開発環境を構築し、必要なすべての静的ファイルなどを使用してアプリケーションを本番用にパッケージ化する責任があります。

目次に戻る


反応DOMとは何ですか?

React DOM は、ブラウザーの React コンポーネントのレンダリングを担当するライブラリです。Reactは、さまざまな環境(モバイルデバイス、デスクトップアプリ、端末など)で使用できるライブラリであることに注意してください。

Reactライブラリは、乾燥するために、コンポーネント、フック、小道具のシステム、および状態の作成のエンジンです...React DOM は、特にブラウザで React コンポーネントをレンダリングするライブラリです。

たとえば、React Nativeも同じことを行いますが、モバイルデバイス用です。

目次に戻る

Reactを学ぶにはどのJavaScriptが必要ですか?

あなたが反応を学ぶために必要なJavaScript。

Reactを学び、習得するには、JavaScriptを知っている必要があります。独自のDSL(ドメイン固有言語)に依存するAngularVueなどの他のフレームワークやライブラリとは異なり、ReactはJSXと呼ばれるJavaScript構文拡張機能を使用します。後で詳しく説明しますが、最終的には、JavaScriptを少なく書くのはまだ構文上の砂糖です。

Reactでは、すべてがJavaScriptです。良くも悪くも。この本は、プログラミング言語の予備知識を当然のことと考えていますが、始める前に、知っておく必要のある最も重要な機能のいくつかを簡単にレビューします。

すでにJavaScriptをマスターしている場合は、この章をスキップして本を続けることができますが、参照のためにこの章をいつでも確認できることを忘れないでください。

EcmaScript Modules o ESModules

EcmaScript モジュールは、異なるファイル間で変数、関数、およびクラスをインポートおよびエクスポートするための JavaScript のネイティブな方法です。今日では、特にWebpackのようなアプリケーションパッケージャーを使用する場合は、常にこの構文を使用します。

一方では、デフォルトでモジュールをエクスポートすることでモジュールを作成できます。

// sayHi.js
// exportamos por defecto el módulo sayHi
export default sayHi (message) {
    console.log(message)
}

// index.js
// este módulo lo podremos importar con el nombre que queramos
import sayHi from './sayHi.js'

// al ser el módulo exportado por defecto podríamos usar otro nombre
import miduHi from './sayHi.js'

モジュールの名前付きエクスポートを作成して、モジュールに名前が割り当てられるようにし、モジュールをインポートするには、エクスポート時に使用された名前を正確に使用する必要があります。

// sayHi.js
// podemos usar exportaciones nombradas para mejorar esto
export const sayHi = (message) => console.log(message)

// y se pueden hacer tantas exportaciones de módulos nombrados como queramos
export const anotherHi = msg => alert(msg)

// index.js
// ahora para importar estos módulos en otro archivo podríamos hacerlo así
import {sayHi, anotherHi} from './sayHi.js'

これまでに見たインポートは、静的インポートとして知られています。これは、そのモジュールをインポートするファイルのアップロード時にそのモジュールがロードされることを意味します。

動的インポートもあるので、プログラムの実行時に、または決定したとき(たとえば、クリックに応答して)ロードされるモジュールをインポートできます。

document.querySelector('button').addEventListener('click', () => {
  // los imports dinámicos devuelven una Promesa
  import('./sayHi.js').then(module => {
    // ahora podemos ejecutar el módulo que hemos cargado
    module.default('Hola')
  })
})

A> 動的インポートは、Webpack や Vite などのパッケージャーを操作する場合にも、一般的なバンドルの外部にロードされるチャンクを作成するため、便利です。目標は?アプリケーションのパフォーマンスを向上させます。

モジュールを操作するための構文は他にもありますが、私たちが見たものを知っていれば、本に従うのに十分でしょう。

重要である理由

まず、Reactは、インポートできるモジュールを通じてライブラリのさまざまな部分を提供します。さらに、コンポーネントはファイルに分割され、それぞれがESModulesを使用してインポートできます。

さらに、パフォーマンスの最適化の問題については、コンポーネントを動的にインポートできるため、ページを使用できるようにするためにロードする必要のある情報が少なくて済むため、ユーザーのエクスペリエンスが向上します。

条件演算子 (三項)

三項は、構文を使用せずに条件を実行する方法です。これは、あまり多くのコードを書かないようにするためのショートカットの一種と言えます。

if

if (number % 2 === 0) {
  console.log('Es par')
} else {
  console.log('Es impar')
}

// usando ternaria
number % 2 === 0 ? console.log('Es par') : console.log('Es impar')

重要である理由

グラフィカルインターフェイスでは、アプリケーションの状態やデータに応じて、画面に何らかのものをレンダリングしたいと思うのはごく普通のことです。これを行うには、JSX内ではるかに読みやすいため、三項を使用する代わりに使用されます。

if

Funciones flecha o Arrow Functions

矢印関数は、ECMAScript 6(またはES2015)標準でJavaScriptに追加されました。最初は、関数式を作成するときの単純な代替構文のようです。

const nombreDeLaFuncion = function (param1, param2) {
  // instrucciones de la función
}

const nombreDeLaFuncion = (param1, param2) => { // con arrow function
  // instrucciones de la función
}

ただし、構文の変更に加えて、Reactで常に使用される矢印関数の他の特性があります。

// return implícito al escribir una sola línea
const getName = () => 'midudev'

// ahorro de parentésis para función de un parámetro
const duplicateNumber = num => num * 2

// se usan mucho como callback en funciones de arrays
const numbers = [2, 4, 6]
const newNumbers = numbers.map(n => n / 2)
console.log(newNumbers) // [1, 2, 3]

また、の価値に関していくつかの変更がありますが、習得することをお勧めしますが、保証付きで本をフォローできる必要はありません。

this

重要である理由

数年前のReactでは主にクラスで作業していましたが、バージョン16.8でフックが壊れて以来、あまり使用されなくなりました。これは、はるかに多くの関数が使用されることを意味します。

さらに、矢印機能は、コンポーネント内で共存していることを簡単に確認できます。たとえば、要素のリストをレンダリングするときは、配列メソッドを実行し、コールバックとして、必ず匿名矢印関数を使用します。

.map

デフォルト値

JavaScript では、引数が渡されない場合に備えて、関数のパラメーターにデフォルト値を指定できます。

// al parámetro b le damos un valor por defecto de 1
function multiply(a, b = 1) {
  return a * b;
}

// si le pasamos un argumento con valor, se ignora el valor por defecto
console.log(multiply(5, 2)) // 10

// si no le pasamos un argumento, se usa el valor por defecto
console.log(multiply(5)) // 5

// las funciones flecha también pueden usarlos
const sayHi = (msg = 'Hola React!') => console.log(msg)
sayHi() // 'Hola React!'

重要である理由

Reactには、コンポーネントとフックという2つの非常に重要な概念があります。ここでは詳しく説明しませんが、重要なことは、両方が関数で構築されていることです。

引数が来ない場合にこれらの関数のパラメーターにデフォルト値を追加できることは、Reactを正常に制御できるようにするための鍵です

たとえば、コンポーネントはパラメーターを受け取らない場合がありますが、それにもかかわらず、コンポーネントにデフォルトの動作を持たせる必要があります。あなたはこの方法でそれを得ることができます。

テンプレートリテラル

リテラル テンプレートまたは文字列テンプレートは、テキスト文字列に埋め込まれた式を許可することで、テキスト文字列を次のレベルに引き上げます。

const inicio = 'Hola'
const final = 'React'

// usando una concatenación normal sería
const mensaje = inicio + " " + final

// con los template literals podemos evaluar expresiones
const mensaje = `${inicio} ${final}`

ご覧のとおり、リテラルテンプレートを使用するには、記号 ''' を使用する必要があります。

さらに、複数行のテキスト文字列を使用することもできます。

重要である理由

Reactでは、これはさまざまなことに使用できます。インターフェイスに表示するテキスト文字列を作成するのは正常であるだけでなく...また、HTML 要素のクラスを動的に作成する場合にも役立ちます。リテラルテンプレートがいたるところにあることがわかります。

省略形プロパティ

ECMAScript 2015 から、省略されたプロパティ名を使用してオブジェクトを開始できます。これは、キーと同じ名前の変数を値として使用する場合は、初期化を一度指定することができます。

const name = 'Miguel'
const age = 36
const book = 'React'

// antes haríamos esto
const persona = { name: name, age: age, book: book }

// ahora podemos hacer esto, sin repetir
const persona = { name, age, book }

重要である理由

Reactではオブジェクトを扱うことが多く、コードの保守と理解を容易にするために、常にできるだけ少ない行を書きたいと考えています。

デストラクチャリング

分解構文は、さまざまな変数の配列またはオブジェクトプロパティから値を抽出できるJavaScript式です。

// antes
const array = [1, 2, 3]
const primerNumero = array[0]
const segundoNumero = array[1]

// ahora
const [primerNumero, segundoNumero] = array

// antes con objetos
const persona = { name: 'Miguel', age: 36, book: 'React' }
const name = persona.name
const age = persona.age

// ahora con objetos
const {age, name} = persona

// también podemos añadir valores por defecto
const {books = 2} = persona
console.log(persona.books) // -> 2

// también funciona en funciones
const getName = ({name}) => `El nombre es ${name}`
getName(persona)

重要である理由

Reactには、この構文を知っていて習得していることを前提とした基本的なコードがたくさんあります。オブジェクトと配列は、インターフェイスで表すデータを格納するのに最適なデータの種類と考えてください。ですから、それらを簡単に治療できることはあなたの人生をはるかに楽にするでしょう。

配列メソッド

JavaScriptで配列を操作する方法を知ることは、あなたが習得することを考慮するための基本です。各メソッドは特定の操作を実行し、さまざまな種類のデータを返します。表示されるすべてのメソッドは、配列の各要素に対して実行されるコールバック(関数)を受け取ります。

最もよく使用される方法のいくつかを確認しましょう。

// tenemos este array con diferentes elementos
const networks = [
  {
    id: 'youtube',
    url: 'https://midu.tube',
    needsUpdate: true
  },
  {
    id: 'twitter',
    url: 'https://twitter.com/midudev',
    needsUpdate: true
  },
  {
    id: 'instagram',
    url: 'https://instagram.com/midu.dev',
    needsUpdate: false
  }
]

// con .map podemos transformar cada elemento
// y devolver un nuevo array
networks.map(singleNetwork => singleNetwork.url)
// Resultado:
  [
    'https://midu.tube',
    'https://twitter.com/midudev',
    'https://instagram.com/midu.dev'
  ]

// con .filter podemos filtrar elementos de un array que no
// pasen una condición determinada por la función que se le pasa.
// Devuelve un nuevo array.
networks.filter(singleNetwork => singleNetwork.needsUpdate === true)
// Resultado:
[
  { id: 'youtube', url: 'https://midu.tube', needsUpdate: true },
  { id: 'twitter', url: 'https://twitter.com/midudev', needsUpdate: true }
]

// con .find podemos buscar un elemento de un array que
// cumpla la condición definida en el callback
networks.find(singleNetwork => singleNetwork.id === 'youtube')
// Resultado:
{ id: 'youtube', url: 'https://midu.tube', needsUpdate: true }

// con .some podemos revisar si algún elemento del array cumple una condición
networks.some(singleNetwork => singleNetwork.id === 'tiktok') // false
networks.some(singleNetwork => singleNetwork.id === 'instagram') // true

重要である理由

Reactでは、UIで表現する必要のあるデータを配列として保存するのがごく普通のことです。これは、多くの場合、それらを処理したり、フィルタリングしたり、情報を抽出したりする必要があることを意味します。これらの方法は最も使用されているため、少なくともこれらの方法を理解し、理解し、習得することが不可欠です。

スプレッド構文

スプレッド構文を使用すると、反復可能オブジェクトまたはオブジェクトを、その情報が期待される別の場所に展開できます。これを使用するには、直前に3つの省略記号を使用する必要があります。

...

const networks = ['Twitter', 'Twitch', 'Instagram']
const newNetwork = 'Tik Tok'
// creamos un nuevo array expandiendo el array networks y
// colocando al final el elemento newNetwork
// utilizando la sintaxis de spread
const allNetworks = [...networks, newNetwork]
console.log(allNetworks)
// -> [ 'Twitter', 'Twitch', 'Instagram', 'Tik Tok' ]

オブジェクトでも同じことを実現できるため、非常に簡単な方法で別のオブジェクトのすべてのプロパティを展開できます。

const midu = { name: 'Miguel', twitter: '@midudev' }
const miduWithNewInfo = {
  ...midu,
  youtube: 'https://youtube.com/midudev',
  books: ['Aprende React']
}
console.log(miduWithNewInfo)
// {
//   name: 'Miguel',
//   twitter: '@midudev',
//   youtube: 'https://youtube.com/midudev',
//   books: [ 'Aprende React' ]
// }

これはコピーを作成することに注意することが重要です、はい、しかし表面的なものです。オブジェクト内にオブジェクトがネストされている場合は、参照を変更できることを覚えておく必要があります。例を見てみましょう。

const midu = {
  name: 'Miguel',
  twitter: '@midudev',
  experience: {
    years: 18,
    focus: 'javascript'
  }
}

const miduWithNewInfo = {
  ...midu,
  youtube: 'https://youtube.com/midudev',
  books: ['Aprende React']
}

// cambiamos un par de propiedades de la "copia" del objeto
miduWithNewInfo.name = 'Miguel Ángel'
miduWithNewInfo.experience.years = 19

// hacemos un console.log del objeto inicial
console.log(midu)

// en la consola veremos que el nombre no se ha modificado
// en el objeto original pero los años de experiencia sí
// ya que hemos mutado la referencia original
// {
//   name: 'Miguel',
//   twitter: '@midudev',
//   experience: { years: 19, focus: 'javascript' }
// }

重要である理由

Reactでは、配列に新しい要素を追加したり、変更せずに新しいオブジェクトを作成したりする必要があるのはごく普通のことです。Rest演算子は、これを実現するのに役立ちます。JavaScriptにおける価値と参照の概念がよくわからない場合は、それをレビューすると便利です。

レストオペレータ

構文は、JavaScript で関数のパラメーターで長い間機能してきました。この手法は rest パラメーターと呼ばれ、関数内に不特定多数の引数を持ち、後で配列としてそれらにアクセスできるようにしました。

...

function suma(...allArguments) {
  return allArguments.reduce((previous, current) => {
    return previous + current
  })
}

これで、rest演算子を使用して、オブジェクトまたは反復可能オブジェクトの残りのプロパティをグループ化することもできます。これは、オブジェクトまたは反復可能オブジェクトから特定の要素を抽出し、残りの部分の表面的なコピーを新しい変数に作成する場合に便利です。

const midu = {
  name: 'Miguel',
  twitter: '@midudev',
  experience: {
    years: 18,
    focus: 'javascript'
  }
}

const {name, ...restOfMidu} = midu

console.log(restOfMidu)
// -> {
//   twitter: '@midudev',
//   experience: {
//     years: 18,
//     focus: 'javascript'
//   }
// }

また、配列でも動作します。

const [firstNumber, ...restOfNumbers] = [1, 2, 3]
console.log(firstNumber) // -> 1
console.log(restOfNumbers) // -> [2, 3]

重要である理由

これは、オブジェクトからプロパティを(比喩的に)削除し、残りのプロパティの表面的なコピーを作成する興味深い方法です。いくつかのパラメータから必要な情報を抽出し、残りを別のレベルに渡すオブジェクトに残すのが興味深い場合があります。

オプションのチェーン

オプションのチェーン演算子を使用すると、オブジェクトのさまざまなレベル内にネストされているプロパティの値を安全に読み取ることができます。

?.

このように、プロパティにアクセスするためにプロパティが存在するかどうかを確認する代わりに、オプションのチェーンを使用します。

const author = {
  name: 'Miguel',
  libro: {
    name: 'Aprendiendo React'
  },
  writeBook() {
    return 'Writing!'
  }
};

// sin optional chaining
(author === null || author === undefined)
    ? undefined
    : (author.libro === null || author.libro === undefined)
    ? undefined
    : author.libro.name 

// con optional chaining
author?.libro?.name

重要である理由

オブジェクトは、多くの UI 要素を表すのに最適なデータ構造です。アイテムを手に入れましたか?記事のすべての情報は確かにオブジェクトで表されます。

UIが大きく複雑になるにつれて、これらのオブジェクトにはより多くの情報が含まれるようになり、保証付きで情報にアクセスできるようにするには、オプションのチェーンを習得する必要があります。

?.


中間

カスタムフックを作成するには?

カスタムフックは、単語で始まる関数であり、他のフックで使用できます。これらは、さまざまなコンポーネントでロジックを再利用するのに理想的です。たとえば、カウンターの状態管理を抽出するカスタムフックを作成できます。

use

// ./hooks/useCounter.js

export function useCounter() {
  const [count, setCount] = useState(0)

  const increment = () => setCount(count + 1)
  const decrement = () => setCount(count - 1)

  return { count, increment, decrement }
}

コンポーネントで使用するには:

import { useCounter } from './hooks/useCounter.js'

function Counter() {
  const { count, increment, decrement } = useCounter()

  return (
    <>
      <button onClick={decrement}>-</button>
      <span>{count}</span>
      <button onClick={increment}>+</button>
    </>
  )
}

目次に戻る


コンポーネントはいくつ持つことができますか?
useEffect

通常、Reactのコンポーネントには1つだけありますが、コンポーネントに必要な数だけ含めることができるということです。それぞれは、コンポーネントがレンダリングされたとき、またはエフェクトの依存関係が変更されたときに実行されます。

useEffect
useEffect

目次に戻る


コンポーネントがツリーからマウント解除されたときにコードを実行するにはどうすればよいですか?

フックを使用してコンポーネントが逆アセンブルされたときにコードを実行し、内部で実行するコードを含む関数を返すことができます。この場合、の最初のパラメーターとして渡された関数は、コンポーネントがマウントされたときに実行され、返される関数は、アンマウントされたときに実行されます。

useEffect
useEffect

import { useEffect } from 'react'

function Component() {
  useEffect(() => {
    console.log('El componente se ha montado')

    return () => {
      console.log('El componente se ha desmontado')
    }
  }, [])

  return <h1>Ejemplo</h1>
}

これは、ブラウザイベントなど、コンポーネントで作成されたリソースをクリーニングしたり、APIへのリクエストをキャンセルしたりする場合に非常に便利です。

目次に戻る


APIへのリクエストを正常にキャンセルする方法
useEffect

API にリクエストを行うときに、この例のように、コンポーネントがアンマウントされたときに実行されないようにキャンセルできます。

AbortController

useEffect(() => {
  // Creamos el controlador para abortar la petición
  const controller = new AbortController()
  // Recuperamos la señal del controlador
  const { signal } = controller
  // Hacemos la petición a la API y le pasamos como options la señal
  fetch('https://jsonplaceholder.typicode.com/posts/1', { signal })
    .then(res => res.json())
    .then(json => setMessage(json.title))
    .catch(error => {
      // Si hemos cancelado la petición, la promesa se rechaza
      // con un error de tipo AbortError
      if (error.name !== 'AbortError') {
        console.error(error.message)
      }
    })

  // Si se desmonta el componente, abortamos la petición
  return () => controller.abort()
}, [])

これは以下でも機能します。

axios

useEffect(() => {
  // Creamos el controlador para abortar la petición
  const controller = new AbortController()
  // Recuperamos la señal del controlador
  const { signal } = controller
  // Hacemos la petición a la API y le pasamos como options la señal
  axios
    .get('https://jsonplaceholder.typicode.com/posts/1', { signal })
    .then(res => setMessage(res.data.title))
    .catch(error => {
      // Si hemos cancelado la petición, la promesa se rechaza
      // con un error de tipo AbortError
      if (error.name !== 'AbortError') {
        console.error(error.message)
      }
    })

  // Si se desmonta el componente, abortamos la petición
  return () => controller.abort()
}, [])

目次に戻る


Reactのフックのルールは何ですか?

Reactのフックには2つの基本的なルールがあります。

  • フックは、機能コンポーネントまたはカスタムフックでのみ使用できます。
  • フックは、コンポーネントの最上位レベルでのみ呼び出すことができます。ループ、条件、またはネストされた関数の内部で呼び出すことはできません。

目次に戻る


と はどう違いますか?
useEffect
useLayoutEffect

どちらも非常に似ていますが、実行される時間にわずかな違いがあります。

useLayoutEffect
レンダリング後にReactがDOMを完全に更新した直後に同期的に実行されます。DOMから要素を取得し、その寸法または画面上の位置にアクセスする必要がある場合に便利です。

useEffect
レンダリング後に非同期的に実行されますが、DOM が更新されているとは限りません。つまり、DOM から要素を回復し、画面上のその寸法または位置にアクセスする必要がある場合、DOM が更新されたという保証がないため、これを行うことはできません。
useEffect

通常、99%の確率でそれを使用したいと思うでしょう、そしてさらに、それはレンダリングをブロックしないので、それはより良いパフォーマンスを持っています。

useEffect

目次に戻る


どちらがより良いクラスのコンポーネントまたは機能コンポーネントですか?

フックはReact 16.8.0に含まれていたため、関数コンポーネントはクラスコンポーネントが実行できるほとんどすべてのことを実行できます。

この質問に対する明確な答えはありませんが、機能コンポーネントは通常、読み取りと書き込みが簡単で、全体的にパフォーマンスが向上する可能性があります。

さらに、フックは機能コンポーネントでのみ使用できます。カスタムフックを作成することで、ロジックを再利用でき、コンポーネントを簡素化できるため、これは重要です。

一方、クラスコンポーネントを使用すると、コンポーネントのライフサイクルを使用できますが、これは、使用できる機能コンポーネントでは実行できません。

useEffect

参照:

目次に戻る


コンポーネントを純粋に保つ方法と、どのような利点がありますか?

純粋なコンポーネントは、状態や副作用のないコンポーネントです。これは、インターフェイスをレンダリングする以外のロジックがないことを意味します。

テストと保守が簡単です。さらに、複雑なロジックがないため、理解しやすくなります。

Reactで純粋なコンポーネントを作成するには、関数を使用します。

function Button({ text }) {
  return (
    <button>
      {text}
    </button>
  )
}

この場合、コンポーネントは文字列である prop を受け取ります。コンポーネントは、prop で受け取ったテキストを含むボタンをレンダリングします。

Button
text
Button
text

目次に戻る


反応の水分補給とは何ですか?

サーバー上でアプリケーションをレンダリングすると、Reactは静的HTMLを生成します。この静的 HTML は、ページに表示される HTML を含む単なる文字列です。

ブラウザーは、静的 HTML を受信すると、ページにレンダリングします。ただし、この静的 HTML には対話機能がありません。イベント、ロジック、状態などはありません。命がないと言えます。

この静的HTMLをインタラクティブにするために、Reactは静的HTMLをReactコンポーネントツリーにする必要があります。これは水分補給と呼ばれます。

このように、クライアントでは、Reactはこの静的HTMLを再利用し、イベントを要素に添付し、コンポーネントに対する効果を実行し、コンポーネントの状態を調整することに専念します。

目次に戻る


サーバーサイドレンダリングとは何ですか、またどのような利点がありますか?

サーバーサイドレンダリングは、サーバー上でHTMLをレンダリングしてクライアントに送信する手法です。これにより、ユーザーは JavaScript が読み込まれる前にアプリのインターフェイスを表示できます。

この手法により、ユーザーエクスペリエンスを向上させ、アプリケーションのSEOを向上させることができます。

目次に戻る


Reactでサーバーサイドレンダリングを最初から作成するにはどうすればよいですか?

Reactでサーバーサイドレンダリングを最初から作成するには、サーバー上でReactコンポーネントをレンダリングできるパッケージを使用できます。

react-dom/server

Expressを使用してReactでサーバーサイドレンダリングを最初から作成する方法の例を見てみましょう。

import express from 'express'
import React from 'react'
import { renderToString } from 'react-dom/server'

const app = express()

app.get('/', (req, res) => {
  const html = renderToString(<h1>Hola mundo</h1>)
  res.send(html)
})

これにより、パスにアクセスするときにアプリケーションの HTML が返されます。

/

<h1 data-reactroot="">Hola mundo</h1>

目次に戻る


Reactの副作用の例を挙げていただけますか?

JavaScript 関数と同様に、React コンポーネントにも副作用があります。副作用とは、コンポーネントがそのスコープ内にない情報を操作または読み取ることを意味します。

ここでは、副作用のあるコンポーネントの簡単な例を見ることができます。コンポーネントの外部にある変数を読み取って変更するコンポーネント。これにより、コンポーネントが持つ値がわからないため、コンポーネントが使用されるたびに何をレンダリングするかを知ることができなくなります。

count

let count = 0

function Counter() {
  count = count + 1

  return (
    <p>Contador: {count}</p>
  )
}

export default function Counters() {
  return (
    <>
      <Counter />
      <Counter />
      <Counter />
    </>
  )

目次に戻る


制御されたコンポーネントと制御されていないコンポーネントの違いは何ですか?それらにはどのような長所と短所がありますか?

Reactでフォームを操作する場合、制御されたコンポーネントと制御されていないコンポーネントの2種類のコンポーネントがあります。

制御されたコンポーネント:コンポーネントの値を制御する状態を持つコンポーネントです。したがって、状態が変更されると、コンポーネントの値は更新されます。

これらのタイプのコンポーネントの利点は、インターフェイスに依存しないため、テストが容易であることです。また、検証を非常に簡単に作成することもできます。欠点は、作成と保守がより複雑になることです。さらに、入力の値が変更されるたびに再レンダリングが発生するため、パフォーマンスが低下する可能性があります。

制御されていないコンポーネント:コンポーネントの値を制御する状態を持たないコンポーネントです。コンポーネントのステータスは、ブラウザによって内部的に制御されます。コンポーネントの値を知るには、DOM の値を読み取る必要があります。

これらのタイプのコンポーネントの利点は、非常に簡単に作成でき、状態を維持する必要がないことです。さらに、入力の値を変更するときに再レンダリングする必要がないため、パフォーマンスが向上します。欠点は、DOMを直接処理し、命令型コードを作成する必要があることです。

// Controlado:
const [value, setValue] = useState('')
const handleChange = () => setValue(event.target.value)

<input type="text" value={value} onChange={handleChange} />

// No controlado:
<input type="text" defaultValue="foo" ref={inputRef} />
// Usamos `inputRef.current.value` para leer el valor del input

目次に戻る


高次コンポーネント(HOC)とは何ですか?

高次コンポーネントは、コンポーネントをパラメーターとして受け取り、コンポーネントを返す関数です。

function withLayout(Component) {
  return function(props) {
    return <main>
      <section>
        <Component {...props} />
      </section>
    </main>
  }
}

この場合、関数はコンポーネントをパラメーターとして受け取り、コンポーネントを返します。返されたコンポーネントは、レイアウト内のパラメータとして渡されたコンポーネントをレンダリングします。

withLayout

これは、コードを再利用できるパターンであるため、簡単な方法で機能、スタイルなどをコンポーネントに挿入できます。

フックの出現により、HOCはあまり人気がなくなりましたが、それでも使用されている場合もあります。

目次に戻る


レンダープロップとは何ですか?

これらは、コンポーネント間でコードを再利用し、コンポーネントのレンダリングに情報を挿入できるようにするReactデザインパターンです。

<DataProvider render={data => (
  <h1>Hello {data.target}</h1>
)}/>

この場合、コンポーネントは prop として関数を受け取ります。そこでは、パラメーターとして受け取った情報を使用して何をレンダリングする必要があるかを説明します。

DataProvider
render

with 関数の実装は次のようになります。

DataProvider

function DataProvider({ render }) {
  const data = { target: 'world' }
  return render(data)
}

このパターンは、コンポーネントの小道具を使用して見つけることもできます。

children

<DataProvider>
  {data => (
    <h1>Hello {data.target}</h1>
  )}
</DataProvider>

実装は似ています。

function DataProvider({ children }) {
  const data = { target: 'world' }
  return children(data)
}

このパターンは、 や などの大規模なライブラリで使用されます。

react-router
formik
react-motion

目次に戻る


コンポーネントのレンダリングに使用できないのはなぜですか?
if

Reactでは、有効なJavaScript式ではなく宣言であるため、コンポーネントのレンダリングにaを使用することはできません。式は値を返す式であり、宣言は値を返しません。

if

JSXでは式しか使用できないため、式である三項を使用します。

// ❌ Esto no funciona
function Button({ text }) {
  return (
    <button>
      {if (text) { return text } else { return 'Click' }}
    </button>
  )
}
// ✅ Esto funciona
function Button({ text }) {
  return (
    <button>
      {text ? text : 'Click'}
    </button>
  )
}

同様に、 、またはコンポーネントのレンダリング内では使用できません。

for
while
switch

目次に戻る


なぜReactのステータスを更新するために関数を使用する必要があるのですか?

Reactのステータスを更新するときは、フックによって提供される関数を使用してステータスを更新する必要があります。

useState

const [count, setCount] = useState(0)

setCount(count + 1)

なぜこれが必要なのですか?まず第一に、Reactのステータスは不変でなければなりません。つまり、状態を直接変更することはできませんが、常に新しい状態の新しい値を作成する必要があります。

これにより、レンダリングするデータに関するUIの整合性が常に正しいものになります。

Por otro lado, llamar a una función le permite a React saber que el estado ha cambiado y que debe re-renderizar el componente si es necesario. Además esto lo hace de forma asíncrona, por lo que podemos llamar a tantas veces como queramos y React se encargará de actualizar el estado cuando lo considere oportuno.

setCount

Volver a índice


¿Qué es el ciclo de vida de un componente en React?

En los componentes de clase, el ciclo de vida de un componente se divide en tres fases:

  • Montaje: cuando el componente se añade al DOM.
  • Actualización: cuando el componente se actualiza.
  • Desmontaje: cuando el componente se elimina del DOM.

Dentro de este ciclo de vida, existe un conjunto de métodos que se ejecutan en el componente.

Estos métodos se definen en la clase y se ejecutan en el orden que se muestran a continuación:

  • constructor
  • render
  • componentDidMount
  • componentDidUpdate
  • componentWillUnmount

En cada uno de estos métodos podemos ejecutar código que nos permita controlar el comportamiento de nuestro componente.

Volver a índice


¿Por qué puede ser mala práctica usar el como key en un listado de React?
index

Cuando renderizamos una lista de elementos, React necesita saber qué elementos han cambiado, han sido añadidos o eliminados.

Para ello, React necesita una key única para cada elemento de la lista. Si no le pasamos una key, React usa el índice del elemento como key.

const List = () => {
  const [items, setItems] = useState(['Item 1', 'Item 2', 'Item 3'])

  return (
    <ul>
      {items.map((item, index) => (
        <li key={index}>{item}</li>
      ))}
    </ul>
  )
}

En este caso, React usa el índice del elemento como . Esto puede ser un problema si la lista se reordena o se eliminan elementos del array, ya que el índice de los elementos cambia.

key

En este caso, React no sabe qué elementos han cambiado y puede que se produzcan errores.

Un ejemplo donde se ve el problema:

const List = () => {
  const [items, setItems] = useState(['Item 1', 'Item 2', 'Item 3'])

  const handleRemove = (index) => {
    const newItems = [...items]
    newItems.splice(index, 1)
    setItems(newItems)
  }

  return (
    <ul>
      {items.map((item, index) => (
        <li key={index}>
          {item}
          <button onClick={() => handleRemove(index)}>Eliminar</button>
        </li>
      ))}
    </ul>
  )
}

Volver a índice


¿Para qué sirve el hook ?
useMemo

El hook es un hook que nos permite memorizar el resultado de una función. Esto quiere decir que si la función que le pasamos como parámetro no ha cambiado, no se ejecuta de nuevo y se devuelve el resultado que ya se había calculado.

useMemo

import { useMemo } from 'react'

function Counter({ count }) {
  const double = useMemo(() => count * 2, [count])

  return (
    <div>
      <p>Contador: {count}</p>
      <p>Doble: {double}</p>
    </div>
  )
}

En este caso, el componente recibe una prop que es un número. El componente calcula el doble de ese número y lo muestra en pantalla.

Counter
count

El hook recibe dos parámetros: una función y un array de dependencias. La función se ejecuta cuando el componente se renderiza por primera vez y cuando alguna de las dependencias cambia, en este ejemplo la prop .

useMemo
count

La ventaja es que si la prop no cambia, se evita el cálculo del doble y se devuelve el valor que ya se había calculado previamente.

count

Volver a índice


¿Es buena idea usar siempre para optimizar nuestros componentes?
useMemo

No. es una herramienta que nos permite optimizar nuestros componentes, pero no es una herramienta mágica que nos va a hacer que nuestros componentes sean más rápidos. A veces el cálculo de un valor es tan rápido que no merece la pena memorizarlo. Incluso, en algunos casos, puede ser más lento memorizarlo que calcularlo de nuevo.

useMemo

Volver a índice


¿Para qué sirve el hook ?
useCallback

El hook es un hook que nos permite memorizar una función. Esto quiere decir que si la función que le pasamos como parámetro no ha cambiado, no se ejecuta de nuevo y se devuelve la función que ya se había calculado.

useCallback

import { useCallback } from 'react'

function Counter({ count, onIncrement }) {
  const handleIncrement = useCallback(() => {
    onIncrement(count)
  }, [count, onIncrement])

  return (
    <div>
      <p>Contador: {count}</p>
      <button onClick={handleIncrement}>Incrementar</button>
    </div>
  )
}

En este caso, el componente recibe una prop que es un número y una prop que es una función que se ejecuta cuando se pulsa el botón.

Counter
count
onIncrement

El hook recibe dos parámetros: una función y un array de dependencias. La función se ejecuta cuando el componente se renderiza por primera vez y cuando alguna de las dependencias cambia, en este ejemplo la prop o la prop .

useCallback
count
onIncrement

La ventaja es que si la prop o la prop no cambian, se evita la creación de una nueva función y se devuelve la función que ya se había calculado previamente.

count
onIncrement

Volver a índice


¿Es buena idea usar siempre para optimizar nuestros componentes?
useCallback

No. es una herramienta que nos permite optimizar nuestros componentes, pero no es una herramienta mágica que nos va a hacer que nuestros componentes sean más rápidos. A veces la creación de una función es tan rápida que no merece la pena memorizarla. Incluso, en algunos casos, puede ser más lento memorizarla que crearla de nuevo.

useCallback

Volver a índice


¿Cuál es la diferencia entre y ?
useCallback
useMemo

La diferencia entre y es que memoriza una función y memoriza el resultado de una función.

useCallback
useMemo
useCallback
useMemo

En cualquier caso, en realidad, es una versión especializada de . De hecho se puede simular la funcionalidad de con :

useCallback
useMemo
useCallback
useMemo

const memoizedCallback = useMemo(() => {
  return () => {
    doSomething(a, b)
  }
}, [a, b])

Volver a índice


¿Qué son las refs en React?

Las refs nos permiten crear una referencia a un elemento del DOM o a un valor que se mantendrá entre renderizados. Se pueden declarar por medio del comando o con el hook .

createRef
useRef

Volver a índice


¿Cómo funciona el hook ?
useRef

En el siguiente ejemplo vamos a guardar la referencia en el DOM a un elemento y vamos a cambiar el foco a ese elemento cuando hacemos clic en el botón.

<input>

import { useRef } from 'react'

function TextInputWithFocusButton() {
  const inputEl = useRef(null)

  const onButtonClick = () => {
    // `current` apunta al elemento inputEl montado
    inputEl.current.focus()
  }

  return (
    <>
      <input ref={inputEl} type="text" />
      <button onClick={onButtonClick}>Focus the input</button>
    </>
  )
}

Creamos una referencia con y la pasamos al elemento como prop . Cuando el componente se monta, la referencia apunta al elemento del DOM.

inputEl
useRef
<input>
ref
inputEl
<input>

Para acceder al elemento del DOM, usamos la propiedad de la referencia.

current

Volver a índice


¿Qué hace el hook ?
useLayoutEffect

useLayoutEffect
funciona igual que el hook , con la excepción de que este se dispara sincrónicamente después de leer todas las mutaciones del DOM.
useEffect

Llama en el nivel superior del componente.

useLayoutEffect

import { useLayoutEffect } from 'react';

useLayoutEffect(() => {
  return () => {
  }
}, []);

useLayoutEffect
recibe dos argumentos:

  • Una función callback que define el efecto.
  • Una lista de dependencias.

Aunque el es el hook de renderizado más usado, si se necesita que los efectos del DOM muten cambiando la apariencia entre el efecto y el renderizado, entonces es conveniente que uses el .

useEffect
useLayoutEffect

Orden de ejecución del
useLayoutEffect

El orden de ejecución del , ya que se ejecuta de forma síncrona, al momento en que React termina de ejecutar todas las mutaciones, pero antes de renderizarlo en pantalla, es el siguiente:

useLayoutEffect

  • El componente se actualiza por algún cambio de estado, props o el padre se re-renderiza
  • React renderiza el componente
  • Tu efecto es ejecutado
  • La pantalla se actualiza “visualmente”

Volver a índice


¿Qué son los componentes stateless?

Los componentes stateless son componentes que no tienen estado. Estos componentes se crean con una y no tienen acceso al estado de la aplicación. La ventaja que tienen estos componentes es que hace que sea más fácil crear componentes puros (que siempre renderizan lo mismo para unas mismas props).

function

// Este es un ejemplo de componente stateless
function Button({ text }) {
  return (
    <button>
      {text}
    </button>
  )
}

Volver a índice


¿Cómo puedes prevenir el comportamiento por defecto de un evento en React?

Para prevenir el comportamiento por defecto de un evento en React, debemos usar el método :

preventDefault

function Form({ onSubmit }) {
  const handleSubmit = (event) => {
    event.preventDefault()
    onSubmit()
  }

  return <form onSubmit={handleSubmit}>
    <input type="text" />
    <button type="submit">Enviar</button>
  </form>
}

Volver a índice


¿Qué es el en React?
StrictMode

El es un componente que nos permite activar algunas comprobaciones de desarrollo en React. Por ejemplo, detecta componentes que se renderizan de forma innecesaria o funcionalidades obsoletas que se están usando.

StrictMode

import { StrictMode } from 'react'

function App() {
  return (
    <StrictMode>
      <Component />
    </StrictMode>
  )
}

Volver a índice


¿Por qué es recomendable exportar los componentes de React de forma nombrada?

Los componentes de React se pueden exportar de dos formas:

  • Exportación por defecto
  • Exportación nombrada

Para exportar un componente por defecto, usamos la palabra reservada :

default

// button.jsx
export default function Button() {
  return <button>Click</button>
}

// App.jsx
import Button from './button.jsx'

function App() {
  return <Button />
}

La gran desventaja que tiene la exportación por defecto es que a la hora de importarlo puedes usar el nombre que quieras. Y esto trae problemas, ya que puedes no usar siempre el mismo en el proyecto o usar un nombre que no sea correcto con lo que importas.

// button.jsx
export default function Button() {
  return <button>Click</button>
}

// App.jsx
import MyButton from './button.jsx'

function App() {
  return <MyButton />
}

// Otro.jsx
import Button from './button.jsx'

function Otro() {
  return <Button />
}

Los exports nombrados nos obligan a usar el mismo nombre en todos los archivos y, por tanto, nos aseguramos de que siempre estamos usando el nombre correcto.

// button.jsx
export function Button() {
  return <button>Click</button>
}

// App.jsx
import { Button } from './button.jsx'

function App() {
  return <Button />
}

Volver a índice


¿Cómo puedes exportar múltiples componentes de un mismo archivo?

Para exportar múltiples componentes de un mismo archivo, podemos usar la exportación nombrada:

// button.jsx
export function Button({children}) {
  return <button>{children}</button>
}

export function ButtonSecondary({children}) {
  return <button class="btn-secondary">{children}</button>
}

Volver a índice


¿Cómo puedo importar de forma dinámica un componente en React?

Para importar de forma dinámica un componente en React debemos usar la función , el método de React y el componente .

import()
lazy()
Suspense

// App.jsx
import { lazy, Suspense } from 'react'

const Button = lazy(() => import('./button.jsx'))

export default function App() {
  return (
    <Suspense fallback={<div>Cargando botón...</div>}>
      <Button />
    </Suspense>
  )
}

// button.jsx
export default function Button() {
  return <button>Botón cargado dinámicamente</button>
}

Vamos a ver en detalle cada uno de los elementos que hemos usado:

La función es parte del estándar de ECMAScript y nos permite importar de forma dinámica un módulo. Esta función devuelve una promesa que se resuelve con el módulo importado.

import()

El método de React nos permite crear un componente que se renderiza de forma diferida. Este método recibe una función que debe devolver una promesa que se resuelve con un componente. En este caso, se resolverá con el componente que tenemos en el fichero . Ten en cuenta que el componente que devuelve debe ser un componente de React y ser exportado por defecto ().

lazy()
button.jsx
lazy()
export default

El componente nos permite mostrar un mensaje mientras se está cargando el componente. Este componente recibe una prop que es el mensaje que se muestra mientras se está cargando el componente.

Suspense
fallback

Volver a índice


¿Cuando y por qué es recomendable importar componentes de forma dinámica?

En React, nuestras aplicaciones están creadas a partir de componentes. Estos componentes se pueden importar de forma estática o dinámica.

La importación de componentes de forma estática es la forma más común de importar componentes en React. En este caso, los componentes se importan en la parte superior del fichero y se renderizan en el código. El problema es que, si siempre lo hacemos así, es bastante probable que estemos cargando componentes que no se van a usar desde el principio.

import { useState } from 'react'
// importamos de forma estática el componente de la Modal
import { SuperBigModal } from './super-big-modal.jsx'

// mostrar modal si el usuario da click en un botón
export default function App () {
  const [showModal, setShowModal] = useState(false)

  return (
    <div>
      <button onClick={() => setShowModal(true)}>Mostrar modal</button>
      {showModal && <SuperBigModal />}
    </div>
  )
}

Este componente se importa de forma estática, por lo que se carga desde el principio. Pero, ¿qué pasa si el usuario no da click en el botón para mostrar la modal? En este caso, está cargando el componente pese a que no lo está usando.

SuperBigModal

Si queremos ofrecer la mejor experiencia a nuestros usuarios, debemos intentar que la aplicación cargue lo más rápido posible. Por eso, es recomendable importar de forma dinámica los componentes que no se van a usar desde el principio.

import { useState } from 'react'
// importamos de forma dinámica el componente de la Modal
const SuperBigModal = lazy(() => import('./super-big-modal.jsx'))

// mostrar modal si el usuario da click en un botón
export default function App () {
  const [showModal, setShowModal] = useState(false)

  return (
    <div>
      <button onClick={() => setShowModal(true)}>Mostrar modal</button>
      <Suspense fallback={<div>Cargando modal...</div>}>
        {showModal && <SuperBigModal />}
      </Suspense>
    </div>
  )
}

De esta forma, la parte de código que importa el componente se carga de forma dinámica, es decir, cuando el usuario da click en el botón para mostrar la modal.

SuperBigModal

Dependiendo del empaquetador de aplicaciones web que uses y su configuración, es posible que el resultado de la carga sea diferente (algunos creará un archivo a parte del bundle principal, otros podrían hacer un streaming del HTML...) pero la intención del código es la misma.

Así que siempre debemos intentar cargar los componentes de forma dinámica cuando no se vayan a usar desde el principio, sobretodo cuando están detrás de la interacción de un usuario. Lo mismo podría ocurrir con rutas completas de nuestra aplicación. ¿Por qué cargar la página de About si el usuario está visitando la página principal?

Volver a índice


¿Sólo se pueden cargar componentes de forma dinámica si se exportan por defecto?

No, no es necesario que los componentes se exporten por defecto para poder cargarlos de forma dinámica. Podemos exportarlos de forma nombrada y cargarlos de forma dinámica... pero no es lo más recomendable ya que el código necesario es mucho más lioso.

// button.jsx
// exportamos el componente Button de forma nombrada
export function Button() {
  return <button>Botón cargado dinámicamente</button>
}

// app.jsx
import { lazy, Suspense } from 'react'

// Al hacer el import dinámico, debemos especificar el nombre del componente que queremos importar
// y hacer que devuelva un objeto donde la key default pasar a ser el componente nombrado
const Button = lazy(
  () => import('./button.jsx')
  .then(({Button}) => ({ default: Button }))
)

export default function App () {
  return (
    <div>
      <Suspense fallback={<div>Cargando botón...</div>}>
        <Button />
      </Suspense>
    </div>
  )
}

Otra opción es tener un fichero intermedio que exporte el componente de forma por defecto y que sea el que importemos de forma dinámica.

// button-component.jsx
// exportamos el componente Button de forma nombrada
export function Button() {
  return <button>Botón cargado dinámicamente</button>
}

// button.jsx
export { Button as default } from './button-component.jsx'

// app.jsx
import { lazy, Suspense } from 'react'

const Button = lazy(() => import('./button.jsx'))

export default function App () {
  return (
    <div>
      <Suspense fallback={<div>Cargando botón...</div>}>
        <Button />
      </Suspense>
    </div>
  )
}

Volver a índice


¿Qué es el contexto en React? ¿Cómo puedo crearlo y consumirlo?

El contexto es una forma de pasar datos a través de la jerarquía de componentes sin tener que pasar props manualmente en cada nivel.

Para crear un contexto en React usamos el hook :

createContext

import { createContext } from 'react'

const ThemeContext = createContext()

Para usar el contexto, debemos envolver el árbol de componentes con el componente :

Provider

<ThemeContext.Provider value="dark">
  <App />
</ThemeContext.Provider>

Para consumir el contexto, debemos usar el hook :

useContext

import { useContext } from 'react'

function Button() {
  const theme = useContext(ThemeContext)
  return <button className={theme}>Haz clic aquí</button>
}

Volver a índice


¿Qué es el en React?
SyntheticEvent

El es una abstracción del evento nativo del navegador. Esto le permite a React tener un comportamiento consistente en todos los navegadores.

SyntheticEvent

Dentro del puede encontrarse una referencia al evento nativo en su atributo

SyntheticEvent
nativeEvent

function App() {
  function handleClick(event) {
    console.log(event)
  }

  return <button onClick={handleClick}>Haz clic aquí</button>
}

Volver a índice


¿Qué es en React?
flushSync

flushSync(callback)
Obliga a React a ejecutar de manera síncrona todas las actualizaciones de los state dentro del callback proporcionado. Así se asegura que el DOM se actualiza inmediatamente.

import { flushSync } from "react-dom"

function App() {
  const handleClick = () => {
    setId(1)
    // component no hace re-render 🚫
    flushSync(() => {
      setId(2)
      // component re-renderiza aquí 🔄
    })
    // component ha sido re-renderizado y el DOM ha sido actualizada ✅
    flushSync(() => {
      setName("John")
      // component no hace re-render 🚫
      setEmail("john@doe.com")
      // component re-renderiza aquí 🔄
    })
    // component ha sido re-renderizado y el DOM ha sido actualizada ✅
  }

  return <button onClick={handleClick}>Haz clic aquí</button>
}

NOTA: puede afectar significativamente el rendimiento. Úsalo con moderación.

flushSync

Volver a índice


¿Qué son los Error Boundaries en React?

Los Error Boundaries son componentes que nos permiten manejar los errores que se producen en el árbol de componentes. Para crear un Error Boundary, debemos crear un componente que implemente el método :

componentDidCatch

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props)
    this.state = { hasError: false }
  }

  static getDerivedStateFromError(error) {
    return { hasError: true }
  }

  componentDidCatch(error, errorInfo) {
    console.log(error, errorInfo)
  }

  render() {
    if (this.state.hasError) {
      return <h1>Algo ha ido mal</h1>
    }

    return this.props.children
  }
}

De esta forma podemos capturar los errores que se producen en el árbol de componentes y mostrar un mensaje de error personalizado mientras evitamos que nuestra aplicación se rompa completamente.

Ahora podemos envolver el árbol de componentes con el componente :

ErrorBoundary

<ErrorBoundary>
  <App />
</ErrorBoundary>

Podemos crear un Error Boundary en cualquier nivel del árbol de componentes, de esta forma podemos tener un control más granular de los errores.

<ErrorBoundary>
  <App />
  <ErrorBoundary>
    <SpecificComponent />
  </ErrorBoundary>
</ErrorBoundary>

Por ahora no existe una forma nativa de crear un Error Boundary en una función de React. Para crear un Error Boundary en una función, puedes usar la librería react-error-boundary.

Volver a índice


¿Qué son las Forward Refs?

El reenvío de referencia o Forward Refs es una técnica que nos permite acceder a una referencia de un componente hijo desde un componente padre.

// Button.jsx
import { forwardRef } from 'react'

export const Button = forwardRef((props, ref) => (
  <button ref={ref} className="rounded border border-sky-500 bg-white">
    {props.children}
  </button>
));

// Parent.jsx
import { Button } from './Button'
import { useRef } from 'react'

const Parent = () => {
  const ref = useRef()

  useEffect(() => {
    // Desde el padre podemos hacer focus
    // al botón que tenemos en el hijo
    ref.current?.focus?.()
  }, [ref.current])

  return (
    <Button ref={ref}>My button</Button>
  )
}

En este ejemplo, recuperamos la referencia del botón (elemento HTML ) y la recupera el componente padre (), para poder hacer focus en él gracias al uso de en el componente hijo ().

<button>
Parent
forwardRef
Button

Para la gran mayoría de componentes esto no es necesario pero puede ser útil para sistemas de diseño o componentes de terceros reutilizables.

Volver a índice


¿Cómo puedo validar el tipo de mis props?

React proporciona una forma de validar el tipo de las props de un componente en tiempo de ejecución y en modo desarrollo. Esto es útil para asegurarnos de que los componentes se están utilizando correctamente.

El paquete se llama y se puede instalar con .

prop-types
npm install prop-types

import PropTypes from "prop-types"

function App(props) {
  return <h1>{props.title}</h1>
}

App.propTypes = {
  title: PropTypes.string.isRequired,
}

En este ejemplo, estamos validando que la prop sea de tipo y que sea obligatoria.

title
string

Existen una colección de PropTypes ya definidas para ayudarte a comprobar los tipos de las props más comunes:

PropTypes.number // número
PropTypes.string // string
PropTypes.array // array
PropTypes.object // objeto
PropTypes.bool // un booleano
PropTypes.func // función
PropTypes.node // cualquier cosa renderizable en React, como un número, string, elemento, array, etc.
PropTypes.element // un elemento React
PropTypes.symbol // un Symbol de JavaScript
PropTypes.any // cualquier tipo de dato

A todas estas se le puede añadir la propiedad para indicar que es obligatoria.

isRequired

Otra opción es usar TypeScript, un lenguaje de programación que compila a JavaScript y que ofrece validación de tipos de forma estática. Ten en cuenta que mientras que TypeScript comprueba los tipos en tiempo de compilación, las PropTypes lo hacen en tiempo de ejecución.

Volver a índice


¿Cómo puedo validar las propiedades de un objeto con PropTypes?

Para validar las propiedades de un objeto que se pasa como prop, podemos usar la propiedad de :

shape
PropTypes

import PropTypes from "prop-types"

function App({ title }) {
  const { text, color } = title
  return <h1 style={{ color }}>{text}</h1>
}

App.propTypes = {
  title: PropTypes.shape({
    text: PropTypes.string.isRequired,
    color: PropTypes.string.isRequired,
  }),
}

Volver a índice


¿Cómo puedo validar las propiedades de un array con PropTypes?

Para validar las propiedades de un array que se pasa como prop, podemos usar la propiedad de :

arrayOf
PropTypes

import PropTypes from "prop-types"

function App({ items }) {
  return (
    <ul>
      {items.map((item) => (
        <li key={item.text}>{item.text}</li>
      ))}
    </ul>
  )
}

App.propTypes = {
  items: PropTypes.arrayOf(
    PropTypes.shape({
      text: PropTypes.string.isRequired,
    })
  ).isRequired,
}

En este caso estamos validando que sea un array y que cada uno de sus elementos sea un objeto con la propiedad de tipo . Además, la prop es obligatoria.

items
text
string

Volver a índice


¿Cómo puedo inyectar HTML directamente en un componente de React?

Una de las razones por las que se creó React es para evitar los ataques XSS (Cross-Site Scripting), impidiendo que un usuario pueda inyectar código HTML en la página.

Por ello, React al intentar evaluar un string que contiene HTML lo escapa automáticamente. Por ejemplo, si intentamos renderizar el siguiente string:

const html = "<h1>My title</h1>"

function App() {
  return <div>{html}</div>
}

Veremos que en lugar de renderizar el HTML, lo escapa:

<div>&lt;h1&gt;My title&lt;/h1&gt;</div>

Sin embargo, hay ocasiones en las que es necesario inyectar HTML directamente en un componente. Ya sea por traducciones que tenemos, porque viene el HTML desde el servidor y ya viene saneado, o por un componente de terceros.

Para ello, podemos usar la propiedad :

dangerouslySetInnerHTML

const html = "<h1>My title</h1>"

function App() {
  return <div dangerouslySetInnerHTML={{ __html: html }} />
}

Ahora sí veremos el HTML renderizado:

<div><h1>My title</h1></div>

Como ves, el nombre ya nos indica que es una propiedad peligrosa y que debemos usarla con cuidado. Intenta evitarla siempre que puedas y sólo recurre a ella cuando realmente no tengas otra opción.

Volver a índice


¿Por qué puede ser mala idea pasar siempre todas las props de un objeto a un componente?

Digamos que tenemos un componente que recibe un objeto con todas las props que necesita:

App
props

function App(props) {
  return <h1>{props.title}</h1>
}

Y que tenemos otro componente que recibe un objeto con todas las props que necesita:

Layout
props

function Layout(props) {
  return (
    <div>
      <App {...props} />
    </div>
  )
}

En este caso, está pasando todas las props que recibe a . Esto puede ser una mala idea por varias razones:

Layout
App

  • Si recibe una prop que no necesita, la pasará a y éste puede que no la use. Esto puede ser confuso para el que lea el código.
    Layout
    App

Experto

¿Es React una biblioteca o un framework? ¿Por qué?

Existe una fina línea hoy en día entre qué es una biblioteca o un framework. Oficialmente, React se autodenomina como biblioteca. Esto es porque para poder crear una aplicación completa, necesitas usar otras bibliotecas.

Por ejemplo, React no ofrece un sistema de enrutado de aplicaciones oficial. Por ello, hay que usar una biblioteca como React Router o usar un framework como Next.js que ya incluye un sistema de enrutado.

Tampoco puedes usar React para añadir las cabeceras que van en el en tu aplicación, y también necesitarás otra biblioteca o framework para solucionar esto.

<head>

Otra diferencia es que React no está opinionado sobre qué empaquetador de aplicaciones usar. En cambio en su propio tutorial ya te indica que debes usar para crear una aplicación, en cambio React siempre te deja la libertad de elegir qué empaquetador usar y ofrece diferentes opciones.

Angular
@angular/cli

Aún así, existe gente que considera a React como un framework. Aunque no hay una definición oficial de qué es un framework, la mayoría de la gente considera que un framework es una biblioteca que incluye otras bibliotecas para crear una aplicación completa de forma opinionada y casi sin configuración.

Por ejemplo, Next.js se podría considerar un framework de React porque incluye React, un sistema de enrutado, un sistema de renderizado del lado del servidor, etc.

Volver a índice


¿Para qué sirve el hook ?
useImperativeHandle

Nos permite definir qué propiedades y métodos queremos que sean accesibles desde el componente padre.

En el siguiente ejemplo vamos a crear un componente que tiene un método que cambia el foco al elemento .

TextInput
focus
<input>

import { useRef, useImperativeHandle } from 'react'

function TextInput(props, ref) {
  const inputEl = useRef(null)

  useImperativeHandle(ref, () => ({
    focus: () => {
      inputEl.current.focus()
    }
  }))

  return (
    <input ref={inputEl} type="text" />
  )
}

Creamos una referencia con y la pasamos al elemento como prop . Cuando el componente se monta, la referencia apunta al elemento del DOM.

inputEl
useRef
<input>
ref
inputEl
<input>

Para acceder al elemento del DOM, usamos la propiedad de la referencia.

current

Para que el componente padre pueda acceder al método , usamos el hook . Este hook recibe dos parámetros: una referencia y una función que devuelve un objeto con las propiedades y métodos que queremos que sean accesibles desde el componente padre.

focus
useImperativeHandle

Volver a índice


¿Para qué sirve el método de React?
cloneElement

Te permite clonar un elemento React y añadirle o modificar las props que recibe.

import { cloneElement } from 'react'

const Hello = ({ name }) => <h1>Hello {name}</h1>

const App = () => {
  const element = <Hello name="midudev" />

  return (
    <div>
      {cloneElement(element, { name: 'TMChein' })}
      {cloneElement(element, { name: 'Madeval' })}
      {cloneElement(element, { name: 'Gorusuke' })}
    </div>
  )
}

En este ejemplo, clonamos que tenía la prop y le pasamos una prop diferente cada vez. Esto renderizará tres veces el componente con los nombres , y . Sin rastro de la prop original.

element
midudev
name
Hello
TMChein
Madeval
Gorusuke

Puede ser útil para modificar un elemento que ya nos viene de un componente padre y del que no tenemos posibilidad de re-crear con el componente.

Volver a índice


¿Qué son los portales en React?

Los portales nos permiten renderizar un componente en un nodo del DOM que no es hijo del componente que lo renderiza.

Es perfecto para ciertos casos de uso como, por ejemplo, modales:

import { createPortal } from 'react-dom'

function Modal() {
  return createPortal(
    <div className="modal">
      <h1>Modal</h1>
    </div>,
    document.getElementById('modal')
  )
}

createPortal
acepta dos parámetros:

  • El primer parámetro es el componente que queremos renderizar
  • El segundo parámetro es el nodo del DOM donde queremos renderizar el componente

En este caso el modal se renderiza en el nodo del DOM.

#modal

Volver a índice


¿Por qué renderiza dos veces la aplicación?
StrictMode

Cuando el modo está activado, React monta los componentes dos veces (el estado y el DOM se preserva). Esto ayuda a encontrar efectos que necesitan una limpieza o expone problemas con race conditions.

StrictMode

¿Qué problemas crees que pueden aparecer en una aplicación al querer visualizar listas de miles/millones de datos?

  • Tiempo de respuesta del servidor: Hacer peticiones de millones de datos no es, en general, una buena estrategia. Incluso en el mejor de los casos, en el que el servidor solo debe devolver los datos sin tratarlos, hay un coste asociado al parseo y envío de los mismos a través de la red. Llamadas con un tamaño desmesurado pueden incurrir en interfaces lentas, e incluso en timeouts en la respuesta.
  • Problemas de rendimiento: Aunque es cierto que React se basa en un modelo declarativo en el cual no debemos tener una exhaustivo control o gestión de cómo se renderiza, no hay que olvidar que malas decisiones técnicas pueden conllevar aplicaciones totalmente inestables incluso con las mejores tecnologías. No es viable renderizar un DOM con millones de elementos, el navegador no podrá gestionarlo y, tarde o temprano, la aplicación no será usable.

Como developers, nuestra misión es encontrar el equilibrio entre rendimiento y experiencia, intentando priorizar siempre cómo el usuario sentirá la aplicación. No hay ningún caso lo suficientemente justificado para renderizar en pantalla miles de datos.

El espacio de visualización es limitado (viewport), al igual que deberían serlo los datos que añadimos al DOM.

Volver a índice


¿Cómo puedes abortar una petición fetch con en React?
useEffect

Si quieres evitar que exista una race condition entre una petición asíncrona y que el componente se desmonte, puedes usar la API de para abortar la petición cuando lo necesites:

AbortController

import { useEffect, useState } from 'react'

function Movies () {
  const [movies, setMovies] = useState([])

  useEffect(() => {
    // creamos un controlador para abortar la petición
    const abortController = new AbortController()

    // pasamos el signal al fetch para que sepa que debe abortar
    fetchMovies({ signal: abortController.signal })
      .then(() => {
        setMovies(data.results)
      }).catch(error => {
        if (error.name === 'AbortError') {
          console.log('fetch aborted')
        }
      })

    return () => {
      // al desmontar el componente, abortamos la petición
      // sólo funcionará si la petición sigue en curso
      abortController.abort()
    }
  })

  // ...
}

// Debemos pasarle el parámetro signal al `fetch`
// para que enlace la petición con el controlador
const fetchMovies = ({ signal }) => {
  return fetch('https://api.themoviedb.org/3/movie/popular', {
    signal // <--- pasamos el signal
  }).then(response => response.json())
}

De esta forma evitamos que se produzca un error por parte de React de intentar actualizar el estado de un componente que ya no existe, además de evitar que se produzcan llamadas innecesarias al servidor.

Volver a índice


¿Qué solución/es implementarías para evitar problemas de rendimiento al trabajar con listas de miles/millones de datos?

Pagination

En lugar de recibir la lista en una sola llamada a la API (lo cual sería negativo tanto para el rendimiento como para el propio servidor y tiempo de respuesta de la API), podríamos implementar un sistema de paginación en el cual la API recibirá un offset o rango de datos deseados. En el FE nuestra responsabilidad es mostrar unos controles adecuados (interfaz de paginación) y gestionar las llamadas a petición de cambio de página para siempre limitar la cantidad de DOM renderizado evitando así una sobrecarga del DOM y, por lo tanto, problemas de rendimiento.

Virtualization

Existe una técnica llamada Virtualización que gestiona cuántos elementos de una lista mantenemos vivos en el DOM. El concepto se basa en solo montar los elementos que estén dentro del viewport más un buffer determinado (para evitar falta de datos al hacer scroll) y, en cambio, desmontar del DOM todos aquellos elementos que estén fuera de la vista del usuario. De este modo podremos obtener lo mejor de los dos mundos, una experiencia integrada y un DOM liviano que evitará posibles errores de rendimiento. Con esta solución también podremos aprovechar que contamos con los datos en memoria para realizar búsquedas/filtrados sin necesidad de más llamadas al servidor.

Puedes consultar esta librería para aplicar Virtualización con React: React Virtualized.

Hay que tener en cuenta que cada caso de uso puede encontrar beneficios y/o perjuicios en ambos métodos, dependiendo de factores como capacidad de respuesta de la API, cantidad de datos, necesidad de filtros complejos, etc. Por ello es importante analizar cada caso con criterio.

Volver a índice


¿Qué es el hook ?
useDebugValue

Nos permite mostrar un valor personalizado en la pestaña de React DevTools que nos permitirá depurar nuestro código.

import { useDebugValue } from 'react'

function useCustomHook() {
  const value = 'custom value'
  useDebugValue(value)
  return value
}

En este ejemplo, el valor personalizado que se muestra en la pestaña de React DevTools es .

custom value

Aunque es útil para depurar, no se recomienda usar este hook en producción.

Volver a índice


¿Qué es el en React?
Profiler

El es un componente que nos permite medir el tiempo que tarda en renderizarse un componente y sus hijos.

Profiler

import { Profiler } from 'react'

function App() {
  return (
    <Profiler id="App" onRender={(id, phase, actualDuration) => {
      console.log({id, phase, actualDuration})
    }}>
      <Component />
    </Profiler>
  )
}

El componente recibe dos parámetros:

Profiler

  • id
    : es un identificador único para el componente
  • onRender
    : es una función que se ejecuta cada vez que el componente se renderiza

Esta información es muy útil para detectar componentes que toman mucho tiempo en renderizarse y optimizarlos.

Volver a índice


¿Cómo puedes acceder al evento nativo del navegador en React?

React no expone el evento nativo del navegador. En su lugar, React crea un objeto sintético que se basa en el evento nativo del navegador llamado . Para acceder al evento nativo del navegador, debemos usar el atributo :

SyntheticEvent
nativeEvent

function Button({ onClick }) {
  return <button onClick={e => onClick(e.nativeEvent)}>Haz clic aquí</button>
}

Volver a índice


¿Cómo puedes registrar un evento en la fase de captura en React?

En React, los eventos se registran en la fase de burbuja por defecto. Para registrar un evento en la fase de captura, debemos añadir al nombre del evento:

Capture

function Button({ onClick }) {
  return <button onClickCapture={onClick}>Haz clic aquí</button>
}

Volver a índice


¿Cómo puedes mejorar el rendimiento del Server Side Rendering en React para evitar que bloquee el hilo principal?

Aunque puedes usar el método para renderizar el HTML en el servidor, este método es síncrono y bloquea el hilo principal. Para evitar que bloquee el hilo principal, debemos usar el método :

renderToString
renderToPipeableStream

let didError = false
const stream = renderToPipeableStream(
  <App />,
  {
    onShellReady() {
      // El contenido por encima de los límites de Suspense ya están listos
      // Si hay un error antes de empezar a hacer stream, mostramos el error adecuado
      res.statusCode = didError ? 500 : 200
      res.setHeader('Content-type', 'text/html')
      stream.pipe(res)
    },
    onShellError(error) {
      // Si algo ha ido mal al renderizar el contenido anterior a los límites de Suspense, lo indicamos.
      res.statusCode = 500
      res.send(
        '<!doctype html><p>Loading...</p><script src="https://raw.githubusercontent.com/midudev/preguntas-entrevista-react/master/clientrender.js"></script>'
      )
    },
    onAllReady() {
      // Si no quieres hacer streaming de los datos, puedes usar
      // esto en lugar de onShellReady. Esto se ejecuta cuando
      // todo el HTML está listo para ser enviado.
      // Perfecto para crawlers o generación de sitios estáticos

      // res.statusCode = didError ? 500 : 200
      // res.setHeader('Content-type', 'text/html')
      // stream.pipe(res)
    },
    onError(err) {
      didError = true
      console.error(err)
    },
  }
)

Volver a índice


¿Qué diferencia hay entre y ?
renderToStaticNodeStream()
renderToPipeableStream()

renderToStaticNodeStream()
devuelve un stream de nodos estáticos, esto significa que no añade atributos extras para el DOM que React usa internamente para poder lograr la hidratación del HTML en el cliente. Esto significa que no podrás hacer el HTML interactivo en el cliente, pero puede ser útil para páginas totalmente estáticas.

renderToPipeableStream()
devuelve un stream de nodos que contienen atributos del DOM extra para que React pueda hidratar el HTML en el cliente. Esto significa que podrás hacer el HTML interactivo en el cliente pero puede ser más lento que .
renderToStaticNodeStream()

Volver a índice


¿Para qué sirve el hook ?
useDeferredValue

El hook nos permite renderizar un valor con una prioridad baja. Esto es útil para renderizar un valor que no es crítico para la interacción del usuario.

useDeferredValue

function App() {
  const [text, setText] = useState('¡Hola mundo!')
  const deferredText = useDeferredValue(text, { timeoutMs: 2000 })

  return (
    <div className='App'>
      {/* Seguimos pasando el texto actual como valor del input */}
      <input value={text} onChange={handleChange} />
      ...
      {/* Pero la lista de resultados se podría renderizar más tarde si fuera necesario */}
      <MySlowList text={deferredText} />
    </div>
  )
}

Volver a índice


¿Para qué sirve el método ?
renderToReadableStream()

Este método es similar a , pero está pensado para entornos que soporten Web Streams como .

renderToNodeStream
Deno

Un ejemplo de uso sería el siguiente:

const controller = new AbortController()
const { signal } = controller

let didError = false

try {
  const stream = await renderToReadableStream(
    <html>
      <body>Success</body>
    </html>,
    {
      signal,
      onError(error) {
        didError = true
        console.error(error)
      }
    }
  )

  // Si quieres enviar todo el HTML en vez de hacer streaming, puedes usar esta línea
  // Es útil para crawlers o generación estática:
  // await stream.allReady

  return new Response(stream, {
    status: didError ? 500 : 200,
    headers: {'Content-Type': 'text/html'},
  })
} catch (error) {
  return new Response(
    '<!doctype html><p>Loading...</p><script src="https://raw.githubusercontent.com/midudev/preguntas-entrevista-react/master/clientrender.js"></script>',
    {
      status: 500,
      headers: {'Content-Type': 'text/html'},
    }
  )
}

Volver a índice


¿Cómo puedo hacer testing de un componente?

Para hacer testing de un componente, puedes usar la función de la librería . Esta función nos permite renderizar un componente y obtener el resultado.

render
@testing-library/react

import { render } from '@testing-library/react'

function Counter() {
  const [count, setCount] = useState(0)
  const increment = () => setCount(count + 1)
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>Increment</button>
    </div>
  )
}

test('Counter', () => {
  const { getByText } = render(<Counter />)

  expect(getByText('Count: 0')).toBeInTheDocument()
  fireEvent.click(getByText('Increment'))
  expect(getByText('Count: 1')).toBeInTheDocument()
})

Volver a índice


¿Cómo puedo hacer testing de un hook?

Para hacer testing de un hook, puedes usar la función de la librería . Esta función nos permite renderizar un hook y obtener el resultado.

renderHook
@testing-library/react-hooks

import { renderHook } from '@testing-library/react-hooks'

function useCounter() {
  const [count, setCount] = useState(0)
  const increment = () => setCount(count + 1)
  return { count, increment }
}

test('useCounter', () => {
  const { result } = renderHook(() => useCounter())

  expect(result.current.count).toBe(0)
  act(() => {
    result.current.increment()
  })
  expect(result.current.count).toBe(1)
})

Volver a índice


¿Qué es Flux?

Flux es un patrón de arquitectura de aplicaciones que se basa en un unidireccional de datos. En este patrón, los datos fluyen en una sola dirección: de las vistas a los stores.

No es específico de React y se puede usar con cualquier librería de vistas. En este patrón, los stores son los encargados de almacenar los datos de la aplicación. Los stores emiten eventos cuando los datos cambian. Las vistas se suscriben a estos eventos para actualizar los datos.

Esta arquitectura fue creada por Facebook para manejar la complejidad de sus aplicaciones. Redux se basó en este patrón para crear una biblioteca de gestión de estado global.

Volver a índice


Errores Típicos en React

¿Qué quiere decir: Warning: Each child in a list should have a unique key prop?

Es un error bastante común en React y que puede parecernos un poco extraño si estamos empezando a aprender esta tecnología. Por suerte, es bastante sencillo de solucionar.

Básicamente, este mensaje aparece en la consola cuando estamos renderizando un listado dentro de nuestro componente, pero no le estamos indicando la propiedad "key". React usa esta propiedad para determinar qué elemento hijo dentro de un listado ha sufrido cambios, por lo que funciona como una especie de identificativo.

De esta manera, React utiliza esta información para identificar las diferencias existentes con respecto al DOM y optimizar la renderización del listado, determinando qué elementos necesitan volverse a calcular. Esto habitualmente pasa cuando agregamos, eliminamos o cambiamos el orden de los items en una lista.

Recomendamos revisar las siguientes secciones:

Volver a índice


React Hook useXXX is called conditionally. React Hooks must be called in the exact same order in every component render

Una de las reglas de los hooks de React es que deben llamarse en el mismo orden en cada renderizado. React lo necesita para saber en qué orden se llaman los hooks y así mantener el estado de los mismos internamente. Por ello, los hooks no pueden usarse dentro de una condición , ni un loop, ni tampoco dentro de una función anónima. Siempre deben estar en el nivel superior de la función.

if

Por eso el siguiente código es incorrecto:

// ❌ código incorrecto por saltar las reglas de los hooks
function Counter() {
  const [count, setCount] = useState(0)

  // de forma condicional, creamos un estado con el hook useState
  // lo que rompe la regla de los hooks
  if (count > 0) {
    const [name, setName] = useState('midu')
  }

  return <div>{count} {name}</div>
}

También el siguiente código sería incorrecto, aunque no lo parezca, ya que estamos usando el segundo de forma condicional (pese a no estar dentro de un ) ya que se ejecutará sólo cuando sea diferente a :

useState
if
count
0

// ❌ código incorrecto por saltar las reglas de los hooks
function Counter() {
  const [count, setCount] = useState(0)

  // si count es 0, no se ejecuta el siguiente hook useState
  // ya que salimos de la ejecución aquí
  if (count === 0) return null

  const [name, setName] = useState('midu')

  return <div>{count} {name}</div>
}

Ten en cuenta que si ignoras este error, es posible que tus componentes no se comporten de forma correcta y tengas comportamientos no esperados en el funcionamiento de tus componentes.

Para arreglar este error, como hemos comentado antes, debes asegurarte de que los hooks se llaman en el mismo orden en cada renderizado. El último ejemplo quedaría así:

function Counter() {
  const [count, setCount] = useState(0)
  // movemos el hook useState antes del if
  const [name, setName] = useState('midu')

  if (count === 0) return null

  return <div>{count} {name}</div>
}

Recomendamos revisar las siguientes secciones:

Volver a índice


Can’t perform a React state update on an unmounted component

Este error se produce cuando intentamos actualizar el estado de un componente que ya no está montado. Esto puede ocurrir cuando el componente se desmonta antes de que se complete una petición asíncrona, por ejemplo:

function Movies () {
  const [movies, setMovies] = useState([])

  useEffect(() => {
    fetchMovies().then(() => {
      setMovies(data.results)
    })
  })

  if (!movies.length) return null

  return (
    <section>
      {movies.map(movie => (
        <article key={movie.id}>
          <h2>{movie.title}</h2>
          <p>{movie.overview}</p>
        </article>
      ))}
    </section>
  )
}

Parece un código inofensivo, pero imagina que usamos este componente en una página. Si el usuario navega a otra página antes de que se complete la petición, el componente se desmontará y React lanzará el error, ya que intentará ejecutar el en un componente (Movies) que ya no está montado.

setMovies

Para evitar este error, podemos usar una variable booleana con que nos indique si el componente está montado o no. De esta manera, podemos evitar que se ejecute el si el componente no está montado:

useRef
setMovies

function Movies () {
  const [movies, setMovies] = useState([])
  const mounted = useRef(false)

  useEffect(() => {
    mounted.current = true

    fetchMovies().then(() => {
      if (mounted.current) {
        setMovies(data.results)
      }
    })

    return () => mounted.current = false
  })

  // ...
}

Esto soluciona el problema pero no evita que se haga la petición aunque el componente ya no esté montado. Para cancelar la petición y así ahorrar transferencia de datos, podemos abortar la petición usando la API :

AbortController

function Movies () {
  const [movies, setMovies] = useState([])

  useEffect(() => {
    // creamos un controlador para abortar la petición
    const abortController = new AbortController()

    // pasamos el signal al fetch para que sepa que debe abortar
    fetchMovies({ signal: abortController.signal })
      .then(() => {
        setMovies(data.results)
      }).catch(error => {
        if (error.name === 'AbortError') {
          console.log('fetch aborted')
        }
      })

    return () => {
      // al desmontar el componente, abortamos la petición
      // sólo funcionará si la petición sigue en curso
      abortController.abort()
    }
  })

  // ...
}

// Debemos pasarle el parámetro signal al `fetch`
// para que enlace la petición con el controlador
const fetchMovies = ({ signal }) => {
  return fetch('https://api.themoviedb.org/3/movie/popular', {
    signal // <--- pasamos el signal
  }).then(response => response.json())
}

Sólo ten en cuenta la compatibilidad de en los navegadores. En caniuse puedes ver que no está soportado en Internet Explorer y versiones anteriores de Chrome 66, Safari 12.1 y Edge 16.

AbortController

Volver a índice


Too many re-renders. React limits the number of renders to prevent an infinite loop

Este error indica que algo dentro de nuestro componente está generando muchos pintados que pueden desembocar en un loop (bucle) infinito. Algunas de las razones por las que puede aparecer este error son las siguientes:

  1. Llamar a una función que actualiza el estado en el renderizado del componente.
function Counter() {
  const [count, setCount] = useState(0)

// ❌ código incorrecto
// no debemos actualizar el estado de manera directa
  setCount(count + 1)

  return <div>{count}</div>
}

Lo que sucede en este ejemplo, es que al renderizarse el componente, se llama a la función para actualizar el estado. Una vez el estado es actualizado, se genera nuevamente un render del componente y se repite todo el proceso infinitas veces.

setCount

Una posible solución sería:

function Counter() {
  // ✅ código correcto
  // se pasa el valor inicial deseado en el `useState`
  const [count, setCount] = useState(1)

  return <div>{count}</div>
}

Llamar directamente a una función en un controlador de eventos.

function Counter() {
  const [count, setCount] = useState(0)

  // ❌ código incorrecto
  //se ejecuta directamente la función `setCount` y provoca un renderizado infinito
  return <div>
    <p>Contador: {count}</p>
    <button onClick={setCount(count + 1)}>Incrementar</button>
  </div>
}

En este código, se está ejecutando la función que actualiza el estado en cada renderizado del componente, lo que provoca renderizaciones infinitas.

setCount

La manera correcta sería la siguiente:

function Counter() {
  const [count, setCount] = useState(0)

  // ✅ código correcto
  // se pasa un callback al evento `onClick`
  // esto evita que la función se ejecute en el renderizado
  return <div>
    <p>Contador: {count}</p>
    <button onClick={() => setCount(count + 1)}>Incrementar</button>
  </div>
}

Usar incorrectamente el Hook de

useEffect
.

Al ver este ejemplo:

function Counter() {
  const [count, setCount] = useState(0)

  // ❌ código incorrecto
  useEffect(() => {
    setCounter(counter + 1)
  }) // 👈️ no colocar el array de dependencias

  return <div>{count}</div>
}

Lo que ocurre, es que al no colocar un array de dependencias en el hook de , estamos provocando que el código que se encuentre dentro se ejecute en cada renderizado del componente. Al llamar al y actualizar el estado, obtenemos nuevamente renderizaciones infinitas.

useEffect
setCounter

これを修正するには、次の操作を行います。

function Counter() {
  const [count, setCount] = useState(0)

  // ✅ código correcto
  // estamos indicando que sólo queremos que el código se ejecute una vez
  useEffect(() => {
    setCounter(counter + 1)
  }, []) //colocamos un array de dependencias vacío.

  return <div>{count}</div>
}

これらは、コードでこのエラーメッセージに遭遇したときに見つけることができる考えられる原因のほんの一部です。この情報を補足する場合は、次のセクションを確認することをお勧めします。

目次に戻る


シャドウDOMと仮想DOMの違いは何ですか?

シャドウ DOM は、DOM の要素内に DOM ノードの個別のツリーを作成できるブラウザー API です。これにより、アプリケーションの他の部分と干渉しないコンポーネントを作成できます。特に Web コンポーネントで使用されます。

仮想 DOM は、メモリ内の DOM の表現です。この表現は、DOM に変更があるたびに作成されます。これにより、現在のDOMを以前のDOMと比較して、実際のDOMにどのような変更を加える必要があるかを判断できます。これは、実際のDOMに最小限の変更を加えるためにReactやその他のライブラリによって使用されます。

目次に戻る