• 카테고리

    질문 & 답변
  • 세부 분야

    프론트엔드

  • 해결 여부

    미해결

Cannot read properties of undefined (reading 'length')

22.06.28 11:17 작성 조회수 343

0

안녕하세요 제로초님, 최대한 질문하지 않고 제힘으로 해결하려했는데 도무지 해결이 안나서 질문드립니다. 

처음 시작 할때는 정상으로 작동을 하는데 'start'버튼을 누를경우 

이런 에러가 뜹니다. 

Uncaught TypeError: Cannot read properties of undefined (reading 'length')

    at Table.jsx:9:24

 

Table 파일에 length 부분이 이상한거 같아 table파일을 확인해 보니, 

 <table>
      {Array(tableData.length).fill().map((tr, i) => <Tr rowIndex={i} />)}
    </table>

이부분에서 오류가 난거 갔습니다. 

오타는 없기에 그렇다면 tableData부분이 문제가 있다고 생각이 들었습니다. 

tableData가 들어있는 파일은 MineSearch.jsx 파일을 샅샅이 뒤졌는데도 오타나 다른부분을 찾지 못하겠습니다..

 

제로초님의 github 에서 MineSearch.jsx 파일을 복사 붙여넣기를 해보니 잘 작동합니다. 

때문에 MineSearch.jsx 파일부분에 오류가 있는게 확실한데... 도무지 찾기가 쉽지 않습니다. 

 MineSearch.jsx 전체를 붙여놓겠습니다. 

의심이 되는 부분만 첨부하라고 하셨는데 거의 모든 부분에 'tableData' 코드를 사용하고 있어서... 일단 첨부합니다.. 

너무 시간이 오래걸릴경우 그냥 질문무시 하셔도 됩니다... 

항상 너무 감사합니다. 

import React, { useEffect, useReducer, createContext, useMemo } from 'react';
import Table from './Table';
import Form from './Form';

export const CODE = {
    MINE: -7,
    NORMAL: -1,
    QUESTION: -2,
    FLAG: -3,
    QUESTION_MINE: -4,
    FLAG_MINE: -5,
    CLICKED_MINE: -6,
    OPENED: 0, // 0 이상이면 다 opened
  };

export const TableContext = createContext({
    tableData:[],
    halted:true,
    dispatch:()=>{}
});

const initialState={
    tableData:[],
    timer:0,
    result:'',
    halted:true,
}

const plantMine = (row, cell, mine) => {
  console.log(row, cell, mine);
  const candidate = Array(row * cell).fill().map((arr, i) => {
    return i;
  });
  const shuffle = [];
  while (candidate.length > row * cell - mine) {
    const chosen = candidate.splice(Math.floor(Math.random() * candidate.length), 1)[0];
    shuffle.push(chosen);
  }
  const data = [];
  for (let i = 0; i < row; i++) {
    const rowData = [];
    data.push(rowData);
    for (let j = 0; j < cell; j++) {
      rowData.push(CODE.NORMAL);
    }
  }

  for (let k = 0; k < shuffle.length; k++) {
    const ver = Math.floor(shuffle[k] / cell);
    const hor = shuffle[k] % cell;
    data[ver][hor] = CODE.MINE;
  }

};

export const START_GAME = 'START_GAME';
export const OPEN_CELL = 'OPEN_CELL';
export const CLICK_MINE = 'CLICK_MINE';
export const FLAG_CELL = 'FLAG_CELL';
export const QUESTION_CELL = 'QUESTION_CELL';
export const NORMALIZE_CELL = 'NORMALIZE_CELL';
export const INCREMENT_TIMER = 'INCREMENT_TIMER';

const reducer = (state, action) =>{
    switch(action.type){
        case START_GAME:
            return{
                ...state,
                tableData:plantMine(action.row, action.cell, action.mine),
                halted:false,
            }
        case OPEN_CELL:{
            const tableData =[...state.tableData];
            tableData[action.row] = [...state.tableData[action.row]];
            tableData[action.row][action.cell]=CODE.OPENED;
            return{
                ...state,
                tableData
            }
        }
        case CLICK_MINE:{
          const tableData =[...state.tableData];
            tableData[action.row] = [...state.tableData[action.row]];
            tableData[action.row][action.cell]=CODE.CLICKED_MINE;
            return{
                ...state,
                tableData,
                halted: true,
            }
        }
        case FLAG_CELL:{
          const tableData =[...state.tableData];
            tableData[action.row] = [...state.tableData[action.row]];
            if (tableData[action.row][action.cell] === CODE.MINE){
              tableData[action.row][action.cell]=CODE.FLAG_MINE;
            } else {
              tableData[action.row][action.cell]=CODE.FLAG;
            }
            return{
                ...state,
                tableData,
            }
        }
        case QUESTION_CELL:{
          const tableData =[...state.tableData];
            tableData[action.row] = [...state.tableData[action.row]];
            if (tableData[action.row][action.cell] === CODE.FLAG_MINE){
              tableData[action.row][action.cell]=CODE.QUESTION_MINE;
            } else {
              tableData[action.row][action.cell]=CODE.QUESTION;
            }
            return{
                ...state,
                tableData,
            }
        }
        case NORMALIZE_CELL:{
          const tableData =[...state.tableData];
            tableData[action.row] = [...state.tableData[action.row]];
            if (tableData[action.row][action.cell] === CODE.QUESTION_MINE){
              tableData[action.row][action.cell]=CODE.MINE;
            } else {
              tableData[action.row][action.cell]=CODE.NORMAL;
            }
            return{
                ...state,
                tableData,
            }
        }

        default: 
          return state;
    }
}

const MineSearch = () => {
  const [state, dispatch] = useReducer(reducer, initialState);
  const { tableData, halted, timer, result } = state;

  const value = useMemo(() => ({ tableData, halted, dispatch }), [tableData, halted]);


  return (
    <TableContext.Provider value={value}>
      <Form />
      <div>{timer}</div>
      <Table />
      <div>{result}</div>
    </TableContext.Provider>
  );
};

export default MineSearch;

답변 1

답변을 작성해보세요.

0

git을 통해 두 파일에서 서로 뭐가 다른건지 확인해보세요.

빠른 답변 감사합니다! 제로초님 좋은 강의 만들어 주셔서 너무 고맙습니다. react가 저에겐 너무 어려웠었는데 제로초님 강의 듣고 react 가 이해가되고 재미를 붙이기 시작했습니다. 제로초님 강의를 들어서 너무 다행입니다. 감사합니다. (.. 질문 댓글 창인데 너무 쓸데없는 이야기했네요.. 그래도 꼭 감사하다고 전해드리고싶었어요.)