DB에서 코멘트를 받아와서 출력해야 하는데,

개행 문자가 comment에 해당되어 있다면

ex) "안녕하세요<br/>공지사항입니다"

=> 안녕하세요

공지사항입니다

 

로 변경해주는 코드

{comment.split("<br/>").map((line) => {
	return (
		<span>
			{line}
			<br />
		</span>
		);
})}

개행문자를 기준으로 split 한 다음 map을 돌려서 개행문자를 라인마다 적용시켜 표출해준다

보통 textarea로 작성하고 db에 바로 넣으면 \n으로 들어가는데, 이 경우에도 split 부분의 string을 \n으로 변경해주면 동일하게 동작한다.

 

MUI의 accordion 컴포넌트에서 헤맸던 부분을 정리하기 위함!

https://mui.com/material-ui/api/accordion/

 

Accordion API - Material UI

API reference docs for the React Accordion component. Learn about the props, CSS, and other APIs of this exported module.

mui.com

MUI 사이트에서 정보를 찾아볼때, 예시코드가 있는 페이지도 좋지만 상세 컨트롤을 원할땐 API가 별도 서술되어 있는 페이지가 원하는 기능을 찾기에 적합하다.

 

1. 한 항목을 클릭하면 다른항목 자동 접기

<Accordion expanded={o.id === selectedNumber} >

expanded 옵션을 사용하면 state 값으로 accordion을 조절 할수 있다!

한번에 모두 접기 + 펼치기 옵션도 해당 버튼 true false 값을 state로 지정하고 expanded에 넣어주면 구현 가능하다.

나 같은 경우는 해당 accordion 클릭시 정보의 id가 선택된 값에 들어가는데, expanded에 해당 값일때만 expanded가 되도록 설정 해두었고, 이렇게 하면 다른 accordion을 클릭하면 이전에 열었던 부분은 자동으로 닫힌다!

 

-) 이렇게 설정하면 해당 아코디언을 다시 눌렀을때 닫혔다 열렸다 하는 부분이 지원되지 않는다ㅠㅠ 여러개를 동시에 여는 동작도 불가함

 

2. 체크박스 이용시에 accordion 동작 막기

소박하게 그려보았따...그림판으로

체크박스가 들어간 아코디언을 만들었는데,

1. (핑크) 체크박스 + 라벨(이름) 클릭시에는 클릭한 이름 state에 해당값을 넣으나 아코디언은 움직이지 않기

2. (하늘) 핑크 부분 외의 여백 누르면 아코디언 열고 닫기가 작동, 체크박스 반응 없음

이런 로직을 원했음

<Accordion>
	<AccordionSummary>
		<div>
			<input
			value={o.id}
			id={o.id}
			type="checkbox"
			// 체크박스를 클릭해도 아코디언이 움직이지 않게 설정
			onClick={(e) => e.stopPropagation()}
			/>
			{/* 라벨 클릭시에는 체크박스 체크되고 아코디언 움직임 비활성화 */}
			<label htmlFor={o.id} onClick={(e) => e.stopPropagation()}>
				{o.name}
			</label>
		</div>
	</AccordionSummary>
	<AccordionDetails>
	// accordion deatils...
	</AccordionDetails>
</Accordion>

input:checkbox와 label에 각각 e.stopPropagation()으로 이벤트 전파를 막아주면 된다!

Material React Table의 페이지네이션 모양이 정말 별로라서..
커스텀 하는 방법을 꽤 오래 찾아야 했어서 써본다

테이블을 사용하는 곳

<MaterialReactTable
	 renderBottomToolbar={({ table }) => {
            return <Pagination table={table} />;
          }}
/>

당연히 data, columns 값 들어가야 한다
여기엔 페이지네이션에 해당하는 부분만 작성함!
table을 넘겨주고, 페이지네이션 용 컴포넌트에 props로 넘긴다
(mrt에서 지원하는게 아닌 내가 만든 컴포넌트가 이름이 Pagination임)

Pagination 컴포넌트

export default function Pagination({ table }: any) {
	const { getPageCount, setPageIndex, getState } = table;
}

일단 props로 받아온 테이블에서 사용할 것들을 할당한다

  • getPageCount : 전체 페이지수
  • setPageIndex : 현재 보게 할 페이지를 설정
  • getState : getState().pagination.pageIndex로 현재 페이지의 index 가져오기

전체페이지 길이, 현재페이지, 현재페이지 세팅 함수 이렇게 세개 가져오는것~


return 하기 전에..

pageArrIdx

기본적으로 페이지를 하나씩 옮기기 때문에, 원하는 모양을 만드려면 5개씩 끊어서 새로운 배열 state를 만들었다
pageArrIdx는 현재 보고있는 arr를 조절하는 state인것

전체 길이를 받아와서, 5개씩 끊어 array를 만든다
ex) 페이지가 총 10개라면 [[1,2,3,4,5] , [6,7,8,9,10]] 이렇게!

const [pageArrIdx, setPageArrIdx] = useState<number>(0);

  // 5페이지 단위로 끊어서 totalpage 길이에 맞춰 배열 생성
  const pageArr = makePageArr(getPageCount());
  function makePageArr(total: number) {
    if (total === 0) return [[]];
    const result = [];
    let start = 1;
    while (start <= total) {
      let end = start + 4;
      if (end > total) end = total;

      const subArray = [];
      for (let i = start; i <= end; i++) {
        subArray.push(i);
      }
      result.push(subArray);
      start += 5;
    }
    return result;
  }

Pagination return 부분

return (
      <div className="w-full flex flex-row my-2 justify-center p-2">
        {pageArrIdx !== 0 && (
          <button
            onClick={() => {
              setPageIndex(0);
              setPageArrIdx(0);
            }}
            className="text-gray-400 border border-gray-300 rounded-lg p-1 mx-1"
          >
            <SkipPreviousIcon />
          </button>
        )}
        {pageArrIdx !== 0 && (
          <button
            onClick={() => {
              setPageArrIdx((prev) => prev - 1);
              setPageIndex(pageArr[pageArrIdx - 1][4] - 1);
            }}
            className="text-gray-400 border border-gray-300 rounded-lg p-1 mx-1"
          >
            <NavigateBeforeIcon />
          </button>
        )}
        {pageArr[pageArrIdx].map((o) => (
          <button
            key={o}
            onClick={() => setPageIndex(o - 1)}
            className={
              "rounded-lg w-[34px] h-[34px] mx-1 border " + (getState().pagination.pageIndex + 1 === o ? "text-pink-400 border-pink-400" : "text-gray-600 border-gray-300")
            }
          >
            {o}
          </button>
        ))}
        {pageArrIdx !== pageArr.length - 1 && (
          <button
            onClick={() => {
              setPageArrIdx((prev) => prev + 1);
              setPageIndex(pageArr[pageArrIdx + 1][0] - 1);
            }}
            className="text-gray-400 border border-gray-300 rounded-lg p-1 mx-1"
          >
            <NavigateNextIcon />
          </button>
        )}
        {pageArrIdx !== pageArr.length - 1 && (
          <button
            onClick={() => {
              setPageIndex(getPageCount() - 1);
              setPageArrIdx(pageArr.length - 1);
            }}
            className="text-gray-400 border border-gray-300 rounded-lg p-1 mx-1"
          >
            <SkipNextIcon />
          </button>
        )}
      </div>
  );

기본 모양은
<< < 1 2 3 4 5 > >>
이런식이고 아이콘은 MUI에서 사용하였다
CSS는 tailwind 이용

<<, >> : 맨 처음, 마지막 페이지로
<, >: 이전,다음 배열로 이동
ex) 현재 [6,7,8,9,10] 이 표현되는 배열일때 < 를 누르면 [1,2,3,4,5]로 이동되고 페이지는 이전에 어디였든 상관없이 5페이지로 간다

이런 로직을 바탕으로 예외처리도 모두 진행하였다!
같은 배열 안에서 페이지 이동은 해당 숫자를 누르면 setPageIndex를 해주면 되는데,

주의할 점은, 페이지 카운트나 pageArr의 숫자는 1부터 시작하는 사용자 기준이지만,
setPageIndex는 기존 방식대로 0부터 사용한다!

(화살표 쓸일이 없으면 전부 안보이게 처리)

'React > MRT' 카테고리의 다른 글

[MRT] 여러 정보를 한컬럼 내에서 사용하기  (0) 2023.10.04

이미 모달이 뜬 상태에서 또 그위에 Modal 기능을 쓰고싶었다
생각보다 간단했음!

 

일단 상단에 모달 선언하기
(모달을 사용하고 있는 컴포넌트)

<DetailModal isDetailToggle={isDetailToggle} setIsDetailToggle={setIsDetailToggle} />
.
.
.
<span onClick={() => setIsDetailToggle(true)}>
모달열기
</span>

그리고 onClick으로 state만 변경해주면 된다

생각보다 검색으로는 답이 명확하게 안나왔었다...

단점은 이게 해당 id의 보고서로 들어가는 버튼이라 새 모달에 id버튼이 있으면 무한으로 계속 열린다는 것
나중에 열리는 횟수를 제한한다던가 하는 다른 방식으로 바꿔야겠다


그리고 Modal위에 Popper를 띄울때!

Modal에 Tooltip이 필요했으나,
닫기 버튼이 포함된 툴팁이어야해서 Tooltip 컴포넌트가 아닌 Popper를 사용하였다

처음에 계속 클릭해도 안떠서 내가 Popper를 잘못 사용한줄 알았었는데,

Modal 자체의 zindex를 넘기지 못해서 Modal 아래에 Popper가 떴던것이었다

 {/* 모달의 zindex가 1300임 */}
<Popper open={tooltipOpen} anchorEl={anchorEl} sx={{ zIndex: "1500", position: "absolute" }} placement="bottom-start">

모달의 zindex인 1300보다 크게 지정해주면 됨!

둘다 간단하지만 조금 오래 헤맸던 기억이 있어서 같이 작성해보았다

내가 필요한 모달은
1. 상세정보로 입장해서 수정 가능한 부분을 수정하고 저장하기
2. 추가 버튼을 누르면 비어있는 부분을 모두 채워서 저장하기
이렇게 두가지였다

한 페이지에서 들어가는것은 물론, CSS가 100% 동일했다.

상세정보의 가짓수가 10가지씩이나 되면 따로 만들었을것도 같지만
수정을 요하는 정보가 많아봤자 2,3개였기 때문에 하나로 이용하기로 했다.

1. 컴포넌트 제작하고 틀 만들기

  • 이건 당연히 둘이 똑같은 틀을 공유한다

2. props로 추가 or 수정을 구별할 값을 넘긴다

  • 나같은 경우엔 data의 id 값이었다.
<DataModal modalId={modalId} />

3. 받아온 id값을 이용하여 나머지를 구성한다.

// 헤더 부분
<h3>{modalId === null ? "정보추가" : "정보상세"}</h3>

4. +)submit 하는 로직에서 받아온 id값에 따라 새 정보를 post 할지, 기존 정보를 update할지 각각 다른 logic 사용하기

 

처음 입사했을땐 state, props에 대해 어렵다고 느껴져서 공부에 손도 가지 않고... 활용하는데 애를 먹었었는데

계속 부딪히고 이들을 좀 더 유연하게 사용하니 좀 더 뿌듯해지는거같다.

작업하다가 표출은 name으로, 내부적으로 사용은 id를 사용해야하는 상황이 생겼다
(클릭하면 Modal이 열려야하는데, id 정보를 보내야 하기 때문)
이전에 작업했던 내역은 아이콘을 무조건 표출하고 아이디값을 고정으로 받아왔었기 때문에 전혀 도움이 되지 않았다ㅠㅠ

 

<이전 작업 예시>

        accessorKey: "id",
        header: "예시"
        Cell: ({ renderedCellValue }: any) => {
          if (renderedCellValue)
            return (
              <span
                className="cursor-pointer"
                onClick={() => {
                  setReportId(renderedCellValue);
                  setReportToggle(true);
                }}
              >
                {<DescriptionIcon />}
              </span>
            );
          else return
          <span className="text-gray-300">{<DescriptionIcon />}</span>;
        },

 

그래서 열심히 찾다가 row에 정보가 담겨있어서 한번에 정보를 사용할수 있다는걸 찾았다!

 

<해결>

       accessorFn: (row) => row.name,
        header: "이름",
        Cell: ({ row }) => <span>{row.original.name}</span>,
        muiTableBodyCellProps: ({ row }) => ({
          onClick: (event) => {
            setIdForModal(row.original.id);
            setIsToggle(true);
          },
          style: {
            cursor: "pointer",
          },
        }),

 

row.original로 해당 row의 데이터 전체에 접근 가능

muiTableBodyCellProps를 사용해야 cell 아무곳이나 클릭했을때 전부 클릭 이벤트를 넣을 수 있다.

'React > MRT' 카테고리의 다른 글

[MRT] 테이블 페이지네이션 커스텀  (0) 2023.10.04