과거 프로그래밍 자료들/React

[웹 게임을 만들며 배우는 React] - 지뢰찾기(1), contextAPI

평부 2022. 9. 30. 16:18

 

 

출처: https://www.inflearn.com/course/web-game-react/dashboard

 

[무료] 웹 게임을 만들며 배우는 React - 인프런 | 강의

웹게임을 통해 리액트를 배워봅니다. Class, Hooks를 모두 익히며, Context API와 React Router, 웹팩, 바벨까지 추가로 배웁니다., - 강의 소개 | 인프런...

www.inflearn.com

 

 

* Cotext API

- 부모와 자식 관계가 다층적일 때 props 물려주기 힘듦

- 예를 들어 부모는 MineSearch.jsx 자식은 Table.jsx > Tr.jsx > Td.jsx일 때 Td가 MineSearch에서 데이터를 가져오고 싶을 때 MineSearch > Table > Tr > Td 순으로 물려줘야 함

- 이 과정에서 MineSearch에서 Td로 바로 데이터를 전달하게 하는 것 = Context API 

 

- 부모 : createContext 사용(useMemo 사용)

▶ MineSearch가 리렌더링 될 때마다  {{ tableData: state.tableData, dispatch }}도 새로 생김

▶ 객체가 새로 생긴다는 것은 contextAPI를 쓰는 자식들도 매번 새로 리렌더링됨(성능적으로 문제 생김)

▶ 매번 새로운 객체가 생기지 않게 useMemo(객체값 기억) 사용 (렌더링 캐싱이라고도 함)

//문제 있는 코드
<TableContext.Provider value={{ tableData: state.tableData, dispatch }}>

//수정한 코드
const value = useMemo(
    	() => ({ tableData: state.tableData, dispatch }),
    	[state.tableData]
    )
<TableContext.Provider value={value}>
//부모
import React, { useReducer, createContext, useMemo } from "react";
import Table from "./Table";

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

const MineSearch = () => {
	const [state, dispatch] = useReducer(reducer, initialState);
  	const value = useMemo(
    	() => ({ tableData: state.tableData, dispatch }),
    	[state.tableData]
    )
    	return (
        <TableContext.Provider value={value}>
        	<Table>
        </TableContext.Provider>
  );
};

 

▶ 자식 : useContext 사용 

[Table.jsx]

import React, { useContext } from "react";
import { TableContext } from "./MineSearch";
import Tr from "./Tr";

const Table = () => {
  const { tableData } = useContext(TableContext);
  return (
    <table>
      {Array(tableData.length)
        .fill()
        .map((tr, i) => (
          <Tr rowIndex={i} />
        ))}
    </table>
  );
};

export default Table;

 

 

[Tr.jsx]

 

import React, { useContext } from "react";
import { TableContext } from "./MineSearch";
import Td from "./Td";

//Table로 부터 rowIndex 받음
const Tr = ({ rowIndex }) => {
  const { tableData } = useContext(TableContext);
  return (
    <tr>
      {tableData[0] &&
        Array(tableData[0].length)
          .fill()
          .map((td, i) => <Td rowIndex={rowIndex} cellIndex={i} />)}
    </tr>
  );
};

export default Tr;

 

 

[Td.jsx]

import React, { useContext } from "react";
import { CODE, TableContext } from "./MineSearch";

const getTdStyle = (code) => {
  switch (code) {
    case CODE.NORMAL:
    case CODE.MINE:
      return {
        background: "#444",
      };
    case CODE.CLICKED_MINE:
    case CODE.OPENED:
      return {
        background: "white",
      };
    case CODE.QUESTION_MINE:
    case CODE.QUESTION:
      return {
        background: "yellow",
      };
    case CODE.FLAG_MINE:
    case CODE.FLAG:
      return {
        background: "red",
      };
    default:
      return {
        background: "white",
      };
  }
};

const getTdText = (data) => {};
const Td = ({ rowIndex, cellIndex }) => {
  const { tableData } = useContext(TableContext);
  return (
    <td style={getTdStyle(tableData[rowIndex][cellIndex])}>
      {getTdText(tableData[rowIndex][cellIndex])}
    </td>
  );
};

export default Td;