Zum Hauptinhalt springen
tsecurity.de LIVE
Echtzeit-Radar & Feeds
Alle RSS Feeds
👥 Community & Social
Sichere ProgrammierungWhy Claude Code keeps writing shell commands that fail on your Mac(20.09.2026 um 21:06 Uhr)
Sichere Programmierungllms.txt v2: What the Spec Says, and What 137,000 Domains Show(20.09.2026 um 21:17 Uhr)
Sicherheitslücken (CVE)NiceTryGPT: Less pattern matching. More actual hacking.(20.09.2026 um 21:19 Uhr)
IT Security VideoActivities BoF (kde2026)(20.09.2026 um 00:00 Uhr)
IT Security Toolsirdoc-app(20.09.2026 um 20:33 Uhr)
Sichere ProgrammierungWhy Claude Code keeps writing shell commands that fail on your Mac(20.09.2026 um 21:06 Uhr)
Sichere Programmierungllms.txt v2: What the Spec Says, and What 137,000 Domains Show(20.09.2026 um 21:17 Uhr)
Sicherheitslücken (CVE)NiceTryGPT: Less pattern matching. More actual hacking.(20.09.2026 um 21:19 Uhr)
IT Security VideoActivities BoF (kde2026)(20.09.2026 um 00:00 Uhr)
IT Security Toolsirdoc-app(20.09.2026 um 20:33 Uhr)
Intelligence View
⚡ tsecurity.de Intelligence

미친 react key

Reagiere als Erste:r — dein Feedback zählt!

map을 통한 렌더링

export function Parent() {
  const [array, setArray] = useState([1, 2, 3, 4, 5]);

  useEffect(() => {
    setTimeout(() => {
      setArray((prev) => [6,7,8,9,10,...prev]);
    }, 3000);
  }, []);

  return (
    <>
      {array.map((item) => (
        <Child key={item} item={item} />
      )}
    </>
  );
}

export function Child({ item }: { item: number }) {
  console.log(item);

  return <>{item}</>
}

실험 결과: 1 2 3 4 5

export function Parent() {
  const [array, setArray] = useState([1, 2, 3, 4, 5]);

  useEffect(() => {
    setTimeout(() => {
      setArray((prev) => [6,7,8,9,10,...prev]);
    }, 3000);
  }, []);

  return (
    <>
      {array.map((_, index) => (
        <Child key={index} item={item} />
      )}
    </>
  );
}

실험 결과: 6, 7, 8, 9, 10, 1, 2, 3, 4, 5

export function Parent() {
  const [array, setArray] = useState([1, 2, 3, 4, 5]);

  useEffect(() => {
    setTimeout(() => {
      setArray((prev) => [...prev.slice(0, 2), 10, ...prev.slice(3,prev.length)]);
    }, 3000);
  }, []);

  return (
    <>
      {array.map((item) => (
        <Child key={item} item={item} />
      )}
    </>
  );
}

export function Child({ item }: { item: number }) {
  return <>{item}</>
}

실험 결과: 10

export function Parent() {
  const [array, setArray] = useState([1, 2, 3, 4, 5]);

  useEffect(() => {
    setTimeout(() => {
      setArray((prev) => [...prev.slice(0, 2), 10, ...prev.slice(3,prev.length)]);
    }, 3000);
  }, []);

  return (
    <>
      {array.map((_, index) => (
        <Child key={index} item={item} />
      )}
    </>
  );
}

export function Child({ item }: { item: number }) {
  return <>{item}</>
}

실험 결과: 10

실험 1
상태: [1, 2, 3, 4, 5] => [6, 7, 8, 9, 10, 1, 2, 3, 4, 5]
결과:

  • react.memo로 감싸지 않았을 경우:
    • key가 item인 경우: 리렌더링시 6, 7, 8, 9, 10, 1, 2, 3, 4, 5 출력
    • key가 index인 경우: 리렌더링시 6, 7, 8, 9, 10, 1, 2, 3, 4, 5 출력
  • react.memo로 감쌌을 경우:
    • key가 item인 경우: 리렌더링시 6, 7, 8, 9, 10 출력
    • key가 index인 경우: 6, 7, 8, 9, 10, 1, 2, 3, 4, 5 출력

실험 2
상태: [1, 2, 3, 4, 5] => [1, 2, 10, 4, 5]
결과:

  • react.memo로 감싸지 않았을 경우:
    • key가 item인 경우: 리렌더링시 1, 2, 10, 4, 5 출력
    • key가 index인 경우: 리렌더링시 1, 2, 10, 4, 5 출력
  • react.memo로 감쌌을 경우:
    • key가 item인 경우: 리렌더링시 10 출력
    • key가 index인 경우: 1, 2, 10, 4, 5 출력

결론:

  • react memo를 사용하면 부모 리렌더링시, 동일한 key에 대해 prop이 변경되지 않는다면 자식의 리렌더링이 발생하지 않는다. 다만 prop이 변경되면 리렌더링이 발생한다.
  • react memo를 사용하지 않는다면 부모 리렌더링시 항상 자식의 리렌더링이 발생한다.

실험 2
부모 컴포넌트 상태: [1, 2, 3] => [3, 2, 1]
자식 컴포넌트 상태: text

export function Parent() {
  const [array, setArray] = useState([1,2,3]);

  useEffect(() => {
    setTimeout(() => {
      setArray((prev) => prev.toReversed());
    }, 3000);
  });

  return (
    <>
      {array.map((item) => (
        <Child key={item} item={item} />
      )}
    </>
  );
}

export function Child({ item }: { item: number }) {
  const [text, setText] = useState("");

  return (
    <>{item}th textfield: 
      <input value={text} onChange={(event) => setText(event.target.value)}/>
    </>
  );
}

결과:

실험 2
부모 컴포넌트 상태: [1, 2, 3] => [3, 2, 1]
자식 컴포넌트 상태: text

export function Parent() {
  const [array, setArray] = useState([1,2,3]);

  useEffect(() => {
    setTimeout(() => {
      setArray((prev) => prev.toReversed());
    }, 3000);
  });

  return (
    <>
      {array.map((item) => (
        <Child key={item} item={item} />
      )}
    </>
  );
}

export function Child({ item }: { item: number }) {
  const [text, setText] = useState("");

  return (
    <>{item}th textfield: 
      <input value={text} onChange={(event) => setText(event.target.value)}/>
    </>
  );
}
export function Parent() {
  const [array, setArray] = useState([1,2,3]);

  useEffect(() => {
    setTimeout(() => {
      setArray((prev) => prev.toReversed());
    }, 3000);
  });

  return (
    <>
      {array.map((item) => (
        <Child key={index} item={item} />
      )}
    </>
  );
}

export function Child({ item }: { item: number }) {
  const [text, setText] = useState("");

  return (
    <>{item}th textfield: 
      <input value={text} onChange={(event) => setText(event.target.value)}/>
    </>
  );
}

결과:

원인:

  • 이전렌더 key의 컴포넌트 종류 === 이후 렌더 컴포넌트 종류일 경우 unmount/mount하지 않는다. 실험 같은 경우 Child로 이전 렌더와 이후 렌더의 컴포넌트 종류 같아서 unmount/mount가 발생하지 않는다.
  • 이전 렌더 컴포넌트와 이후 렌더 컴포넌트에서 같은 종류의 컴포넌트 instance에 대해서는, state가 유지된다. 즉, key와 state가 매핑된다. 따라서 index를 key로 사용하였을 경우, array 순서 변경이 일어날 때 index와 자식 상태(text)가 매핑되어서 순서 변경이 제대로 일어나지 않는다. 반면 item을 key로 사용하였을 경우에는 array 순서 변경이 일어날 때 item와 자식 상태(text)가 매핑되어서 순서 변경이 정상적으로 같이 일어난다.

결론

  • index를 key로 사용해도 괜찮다. 다만 요소 순서의 변경이 일어날 때는 index를 key로 사용하면 안 된다.
  • 자식 컴포넌트의 상태가 key와 매핑되는데, index와 매핑되는 경우 요소 순서 변경이 일어나도 상태 순서 변경이 일어나지 않기 때문이다.
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten 미친 react key

Thematisch verwandte Begriffe: react · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Zum Aktualisieren ziehen
ZERO-DAY CVE-2026-93956 | A flaw has been found in olivier-ls PHP-FTS up to 1.1.2. Affected by thi…
Advisory →
TTS Reader • tsecurity.de Voice
tsecurity.de Icon
tsecurity.de App
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag
Themen-Radar & Intelligence Matrix
Echtzeit-Taxonomie nach Angriffsvektoren & Plattformen

tsecurity.de Live Threat Radar

🔴 LIVE RADAR
MONITORING
AKTIV
CVE-DATENBANK
LIVE
🔍
Community Radar & Live Chat
Sentinel Bot online • Live-Stream
Dein Cluster: Security Explorer
Match:
lädt…
Verbindung zum Community-Stream wird aufgebaut...
Bearbeitungsmodus — Senden überschreibt deine Nachricht
Community-Puls — was gerade passiert
lädt…
Aktivitäten deiner Analysten
lädt…
Neues Thema oder Eilmeldung einreichen

Reiche interessante Links, Zero-Days oder Debatten ein. Die Community entscheidet per Upvote über die Veröffentlichung.

Heiß diskutierte Einreichungen
🔖 Gespeicherte Artikel
📂 Keine gespeicherten Artikel vorhanden.
Zurück Ziehen Vor
Links: vorheriger Artikel Rechts: nächster Artikel unten: schließen
News NIS-2 Frühwarnung Tier-1 Intel ⏱️ 3 Min vor 10 Min
Artikeldaten werden geladen...

Zurück: vorheriger Vor: nächster
↗ Original-Quelle
Social Reaktionen Deine Reaktion zählt
Einstufung & Relevanz-Poll 0 Stimmen
In sozialen Netzwerken teilen 1-Klick