nprimem
@nprimem (与太郎)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

Reactのwarningの消し方(おそらくkey関連)

解決したいこと

Reactのwarningの消し方(おそらくkey関連)

28日に勉強スタートした未熟者なのでしょうもないところで勘違いを起こしていると思います。が、3時間しっかりと悩みました。

App.tsx
import React, { useState } from 'react';
import './App.css';
import { Board } from './compornents/Board';

type stone = {
  //key
  key : number
  //trueであれば置ける
  isPut: boolean;
  //trueであれば黒, falseであれば白, nullは石がない状態
  isColor: boolean | null;
}

type stoneLine = {
  lineId: number,
  stoneLine: stone[],
}

const firstBoard: stoneLine[] = 
[
  {lineId:0, stoneLine:[
    {key:0, isPut: false, isColor: null},{key:1, isPut: false, isColor: null},{key:2, isPut: false, isColor: null},{key:3, isPut: false, isColor: null},
    {key:4, isPut: false, isColor: null},{key:5, isPut: false, isColor: null},{key:6, isPut: false, isColor: null},{key:7, isPut: false, isColor: null}
  ]},
  {lineId:1, stoneLine:[
    {key:8, isPut: false, isColor: null},{key:9, isPut: false, isColor: null},{key:10, isPut: false, isColor: null},{key:11, isPut: false, isColor: null},
    {key:12, isPut: false, isColor: null},{key:13, isPut: false, isColor: null},{key:14, isPut: false, isColor: null},{key:15, isPut: false, isColor: null}
  ]},
  {lineId:2, stoneLine:[
    {key:16, isPut: false, isColor: null},{key:17, isPut: false, isColor: null},{key:18, isPut: false, isColor: null},{key:19, isPut: false, isColor: null},
    {key:20, isPut: true, isColor: null},{key:21, isPut: false, isColor: null},{key:22, isPut: false, isColor: null},{key:23, isPut: false, isColor: null}
  ]},
  {lineId:3, stoneLine:[
    {key:24, isPut: false, isColor: null},{key:25, isPut: false, isColor: null},{key:26, isPut: false, isColor: null},{key:27, isPut: false, isColor: true},
    {key:28, isPut: false, isColor: false},{key:29, isPut: true, isColor: null},{key:30, isPut: false, isColor: null},{key:31, isPut: false, isColor: null}
  ]},
  {lineId:4, stoneLine:[
    {key:32, isPut: false, isColor: null},{key:33, isPut: false, isColor: null},{key:34, isPut: true, isColor: null},{key:35, isPut: false, isColor: false},
    {key:36, isPut: false, isColor: true},{key:37, isPut: false, isColor: null},{key:38, isPut: false, isColor: null},{key:39, isPut: false, isColor: null}
  ]},
  {lineId:5, stoneLine:[
    {key:40, isPut: false, isColor: null},{key:41, isPut: false, isColor: null},{key:42, isPut: false, isColor: null},{key:43, isPut: true, isColor: null},
    {key:44, isPut: false, isColor: null},{key:45, isPut: false, isColor: null},{key:46, isPut: false, isColor: null},{key:47, isPut: false, isColor: null}
  ]},
  {lineId:6, stoneLine:[
    {key:48, isPut: false, isColor: null},{key:49, isPut: false, isColor: null},{key:50, isPut: false, isColor: null},{key:51, isPut: false, isColor: null},
    {key:52, isPut: false, isColor: null},{key:53, isPut: false, isColor: null},{key:54, isPut: false, isColor: null},{key:55, isPut: false, isColor: null}
  ]},
  {lineId:7, stoneLine:[
    {key:56, isPut: false, isColor: null},{key:57, isPut: false, isColor: null},{key:58, isPut: false, isColor: null},{key:59, isPut: false, isColor: null},
    {key:60, isPut: false, isColor: null},{key:61, isPut: false, isColor: null},{key:62, isPut: false, isColor: null},{key:63, isPut: false, isColor: null}
  ]}
]
;

function App() {
  
const [stoneBoardArr, setStoneBoardArr] = useState<stoneLine[]>(firstBoard);

const onclickBoard = () => {
  setStoneBoardArr(firstBoard);
}

  return (
    <Board stoneBoardArr={stoneBoardArr} />
  );
}

export default App;
./component/Board.tsx
import React from 'react';

type stone = {
    //key
    key: number;
    //trueであれば置ける
    isPut: boolean;
    //trueであれば黒, falseであれば白, nullは石がない状態
    isColor: boolean | null;
  }

type stoneLine = {
    lineId: number,
    stoneLine: stone[],
  }

type Props = {
    stoneBoardArr: stoneLine[]
}



export const Board = (props:Props) => {
    const { stoneBoardArr } = props;
    return (
        <>
        {stoneBoardArr.map((stoneLine:stoneLine) => {
           return(
            <>
                <div key={stoneLine.lineId} style={S_board}>
                        {stoneLine.stoneLine.map((stone:stone) => {
                            if (stone.isColor===null){
                                return (
                                    <div key={stone.key} style={stone.isPut ? S_canPutStoneNone : S_stoneNone}></div>
                                    )
                                } else if (stone.isColor){
                                    return (
                                        <div key={stone.key} style={S_stoneBlack}></div>
                                    )
                                } else {
                                    return (
                                        <div key={stone.key} style={S_stoneWhite}></div>
                                    )
                                }
                        })}
                </div>
            </>)
        })}
        </>
    )
}
    
const S_board = {
    display: "flex",
}

const S_stoneNone = {
    backgroundColor : "green",
    height:"50px",
    width:"50px",
    border: "solid 2px #000000",
    marginTop: "-2px",
    marginLeft: "-2px"
}

const S_canPutStoneNone = {
    backgroundColor : "#006400",
    height:"50px",
    width:"50px",
    border: "solid 2px #000000",
    marginTop: "-2px",
    marginLeft: "-2px"
}

const S_stoneBlack = {
    backgroundColor : "green",
    height:"50px",
    width:"50px",
    border: "solid 2px #000000",
    backgroundImage:"radial-gradient(circle closest-side,#000000 80%,transparent 60%)",
    marginTop: "-2px",
    marginLeft: "-2px"
}

const S_stoneWhite = {
    backgroundColor : "green",
    height:"50px",
    width:"50px",
    border: "solid 2px #000000",
    backgroundImage:"radial-gradient(circle closest-side,#FFFFFF 80%,transparent 60%)",
    marginTop: "-2px",
    marginLeft: "-2px"
}

発生している問題・エラー

image.png

React+TypeScriptです。

自分で試したこと

ユニークな値として
stone型にはkeyを
stoneLine形にはlineIdを追加したのに消えてくれないです。

0

2Answer

上の Yuma 様と同じく。

補足として、配列の中での key の指定のしかたについて説明します。


質問でのコードは以下のような階層構造になっています。

<> ~ </> は React.Fragment という要素を書くための省略記法です。

books.map((book) => (
  <>
    <div key={/* key を指定*/}>
      <div key={/* key を指定*/}>
        中身
      </div>
    </div>
  </>
))

// .map を実行した結果
[
  (
    <Fragment>
      <div key={0}><div key={0}></div></div>
    </Fragment>
  ),
  (
    <Fragment>
      <div key={1}><div key={1}></div></div>
    </Fragment
  )
]

これでは要素が追加・削除された時に各要素の状態がおかしくなるケース(今回は当てはまらない)があるので、 React は警告を表示してくれます。

上の例では、key を各要素そのものでなくその子・孫要素に 設定してしまっていますが、 正しくは配列の各要素そのものに設定しないといけません。


どうしても Fragment を使わないといけないときには、 <> の記法は使えず、以下のように明示的に書く必要があります。

books.map((book) => (
  <Fragment key={/* key を指定*/}>
  中身
  </Fragment>
))

// .map を実行した結果
[
  (
    <Fragment key={0}>
      <div></div>
    </Fragment>
  ),
  (
    <Fragment key={1}>
      <div></div>
    </Fragment>
  )
]

3Like

Comments

  1. @nprimem

    Questioner

    詳しくありがとうございます。とても参考になります。
    私の学習が悪いのですがFragmentという言葉すら知らず、ただreturnには<>と認識しておりました。
    今後も励みます。お忙しい中ありがとうございました

map の中にも <> を入れてる影響ですかね?
以下で試すとWarningは起こりませんでした

  return (
    <>
      {stoneBoardArr.map((stoneLine: stoneLine) => {
        return (
          <div key={stoneLine.lineId} style={S_board}>
            {stoneLine.stoneLine.map((stone: stone) => {
              if (stone.isColor === null) {
                return (
                  <div key={stone.key} style={stone.isPut ? S_canPutStoneNone : S_stoneNone}></div>
                )
              } else if (stone.isColor) {
                return (
                  <div key={stone.key} style={S_stoneBlack}></div>
                )
              } else {
                return (
                  <div key={stone.key} style={S_stoneWhite}></div>
                )
              }
            })}
          </div>
        )
      })}
    </>
  );
2Like

Comments

  1. @nprimem

    Questioner

    ありがとうございます。返事が遅くなり申し訳ございません。
    return には<>と間違った認識をしていたのですね。
    気づかせてくださりありがとうございます。これからも精進いたします

Your answer might help someone💌