TableContent를 사용할 때 테이블 칼럼 값을 tbody의 tr들로 뿌려주기 위해 DynamicTableContent를 사용한다.
TableContent에서 데이터 없을 경우의 처리를 위해 삼항연산자를 정의해두고, DynamicTableContent 단에서 데이터가 제대로 안 들어가게 되면 TableContent 단에서 캐치하게끔 의도했는데, 리턴하는 JSX 값이 <></>도, 대놓고 NULL을 리턴해도 TableContent의 props인 tableContent는 비어있다는 것을 인식하지 못하는 이슈가 발생했다.
<ViewTable
tableHeader={<DynamicTableHeader thItems={thItems} />}
tableContent={<DynamicTableContent items={[items]} textAligns={textAligns} />}
hasPage
hasFilter
/>
interface DynamicTableContentProps<T extends Record<string, CellType>> {
items: T[];
textAligns?: string[];
columnsCallback?: (() => void)[];
focus?: number;
}
const DynamicTableContent = <T extends Record<string, CellType>>({
items,
textAligns,
columnsCallback,
focus,
}: DynamicTableContentProps<T>) => {
if (items.length === 0) return null; // 이래도 비어있다 인식을 못함
return (
<>
{items.length > 0 &&
items.map((item, index) => (
<tr
key={index}
onClick={columnsCallback && columnsCallback[index]}
className={index == focus ? 'selected' : ''}
>
{Object.keys(item).map((key, keyIndex) => (
<td key={key} className={textAligns && textAligns[keyIndex]}>
{item[key]}
</td>
))}
</tr>
))}
</>
);
};
export default DynamicTableContent;
import * as S from './styles';
interface TableContentProps {
tableHeader: React.ReactNode;
tableContent: React.ReactNode;
}
const TableContent = ({ tableHeader, tableContent }: TableContentProps) => {
// tableContent 가 비어있어도 삼항 연산자가 인식을 하지 못함
return (
<S.TableRoot>
<S.TableHeader>{tableHeader}</S.TableHeader>
{tableContent ? (
<S.TableBody>{tableContent}</S.TableBody>
) : (
<S.Empty>
<div>리스트가 없습니다</div>
</S.Empty>
)}
</S.TableRoot>
);
};
export default TableContent;
null을 반환하는 컴포넌트도 React Element이다React에서는 null을 반환하는 JSX 코드가 있어도 내부적으로 React.createElement() 가 호출된다.
즉, JSX는 항상 React 요소(ReactElement)로 변환되며, 이는 $$typeof: Symbol(react.element) 속성을 가지게 된다.
null을 반환하는 children 격의 컴포넌트를 콘솔로 찍으면 다음과 같은 값이 나온다.
{
"$$typeof": "Symbol(react.element)",
"key": null,
"props": {
"items": null,
"textAligns": Array(9),
},
"ref": null,
"type": "({ items, textAligns, columnsCallback, focus }) => {…}",
"_owner": "FiberNode",
"_store": {
"validated": true
},
"_self": undefined,
"_source": {
"fileName": "C:/Users/qwerg/Desktop/work/wiseon_master_admin/src/pages/ManagementUpdatePage/index.tsx",
"lineNumber": 42,
"columnNumber": 25
}
}
TableContent에서 하던 삼항 연산 분기를 TableContent가 사용할 element를 jsx로 리턴해주는 DynamicTableContent 컴포넌트 단에서 진행하도록 수정해주었다. 이렇게 되면 분기를 통해 최종적으로 렌더링되야 할 요소들이 의도했던 대로 TableContent에 전달되어진다.
interface DynamicTableContentProps<T extends Record<string, CellType>> {
items: T[];
textAligns?: string[];
columnsCallback?: (() => void)[];
focus?: number;
}
const DynamicTableContent = <T extends Record<string, CellType>>({
items,
textAligns,
columnsCallback,
focus,
}: DynamicTableContentProps<T>) => {
if (items.length === 0) return null; // 이래도 비어있다 인식을 못함
return (
<>
{items.length > 0 &&
items.map((item, index) => (
<tr
key={index}
onClick={columnsCallback && columnsCallback[index]}
className={index == focus ? 'selected' : ''}
>
{Object.keys(item).map((key, keyIndex) => (
<td key={key} className={textAligns && textAligns[keyIndex]}>
{item[key]}
</td>
))}
</tr>
))}
</>
);
};
export default DynamicTableContent;
import * as S from './styles';
interface DynamicTableContentProps<T extends Record<string, CellType>> {
items: T[];
textAligns?: string[];
columnsCallback?: (() => void)[];
focus?: number;
}
const DynamicTableContent = <T extends Record<string, CellType>>({
items,
textAligns,
columnsCallback,
focus,
}: DynamicTableContentProps<T>) => {
return (
<>
{items && items.length > 0 ? (
<S.TableBody>
{items.map((item, index) => (
<tr
key={index}
onClick={columnsCallback && columnsCallback[index]}
className={index == focus ? 'selected' : ''}
>
{Object.keys(item).map((key, keyIndex) => (
<td key={key} className={textAligns && textAligns[keyIndex]}>
{item[key]}
</td>
))}
</tr>
))}
</S.TableBody>
) : (
<S.Empty>
<div>리스트가 없습니다</div>
</S.Empty>
)}
</>
);
};
export default DynamicTableContent;