본문 바로가기
IT/React

RN(ReactNative) TDD TODO 앱 만들기 #3

by DOSGamer 2022. 8. 10.
반응형

 

이전 테스트시에

한가지 Warning 이 보이는데 

Warning: Each child in a list should have a unique "key" prop.

TaskList 는 여러 개의 Task 가 쌓이면 스크롤이 생기도록 ScrollView 를 사용하고 있는데 
ScrollView 내부의 리스트에 unique 한 key 를 prop 로 넣어달라는 것이다

 

TaskList 에 key 추가

TaskList-test.js 의 초기 데이터에 id 를 추가한다

//TaskList-test.js
...생략...

describe('TaskList render', () => {
  props = {
    data: [
      {id: '1', subject: 'Learn React Native'},
      {id: '2', subject: 'Create a React Native app'},
    ],
  };

...생략...

테스트 하면 당연히 에러

TaskList.jsx 도 변경된 데이터에 맞게 수정해준다

import React from 'react';
import {ScrollView, Text} from 'react-native';

const TaskList = ({data}) => {
  return (
    <ScrollView>
      {data.map(item => (
        <Text key={item.id}>{item.subject}</Text>
      ))}
    </ScrollView>
  );
};

export default TaskList;

TaskList 가 잘 동작되니 HomeScreen 의 초기 데이터도 수정

//HomeScreen.jsx
import React from 'react';

import Title from '../components/Title';
import TaskInput from '../components/TaskInput';
import TaskList from '../components/TaskList';

const initialData = [
  {id: '1', subject: 'Learn React Native'},
  {id: '2', subject: 'Create a React Native app'},
];

export default function App() {
  return (
    <>
      <Title title="Todo TDD" />
      <TaskInput />
      <TaskList data={initialData} />
    </>
  );
}

 

이제 key 를 추가해줬기 때문에 unique key 경고는 나오지 않는다

 

 

TaskItem 컴포넌트 만들기

이전 까지 TaskList 에서 Text 를 여러개 뿌렸다면 Icon 과 Text 를 조합하여 사용하는 TaskItem 을 만들어서 TaskList 에 넣어준다

테스트 컴포넌트를 만듭니다

TaskItem-test.js 생성

import 'react-native';
import React from 'react';
import {render, screen} from '@testing-library/react-native';

import TaskItem from '../TaskItem';

let props;

function getAppComponent(temProps) {
  return <TaskItem {...temProps} />;
}

describe('TaskItem render', () => {
  props = {key: '1', data: {id: '1', subject: 'Learn React Native'}};

  it('should render checkbox Icon', () => {
    render(getAppComponent(props));
    const element = screen.getByTestId('checkbox');
    expect(element).toBeTruthy();
  });
  it('should render subject', () => {
    render(getAppComponent(props));
    const element = screen.getByText('Learn React Native');
    expect(element).toBeTruthy();
  });
  it('should render edit Icon', () => {
    render(getAppComponent(props));
    const element = screen.getByTestId('edit');
    expect(element).toBeTruthy();
  });
  it('should render delete Icon', () => {
    render(getAppComponent(props));
    const element = screen.getByTestId('delete');
    expect(element).toBeTruthy();
  });
});

테스트를 하면 아직 TaskItem.jsx 를 만들지 않았으니 당연히 실패

 

이제 TaskItem 을 만든다

src > components > TaskItem.jsx

TaskItem 의 구성은  체크박스 아이콘 + Text + 수정 아이콘 + 삭제 아이콘 으로 구성한다

아이콘은 react-native-vector-icons/Feather 를 사용합니다

//TaskItem.jsx

import React from 'react';
import FeatIcon from 'react-native-vector-icons/Feather';
import {Dimensions, StyleSheet, View, Text} from 'react-native';

FeatIcon.loadFont();

const FeatherIcon = ({name, size, color, testId}) => {
  return (
    <FeatIcon
      name={name}
      size={IconSizes[size]}
      color={color}
      testID={testId}
    />
  );
};

const IconSizes = {
  small: 13,
  medium: 18,
  large: 23,
  extraLarge: 27,
};

const TaskItem = props => {
  const {data} = props;
  return (
    <View style={styles.taskItem}>
      <FeatherIcon name="square" size="small" color="green" testId="checkbox" />
      <Text style={styles.subject}>{data.subject}</Text>
      <FeatherIcon name="edit-2" size="medium" color="blue" testId="edit" />
      <FeatherIcon name="delete" size="medium" color="red" testId="delete" />
    </View>
  );
};

const styles = StyleSheet.create({
  taskItem: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-around',
    marginLeft: 8,
    width: Dimensions.get('window').width - 15,
  },
  subject: {
    fontSize: 20,
    flex: 1,
    color: 'black',
  },
});

export default TaskItem;

 

파일 만들면 테스트 실행하여

체크박스 아이콘, 제목, 수정 아이콘, 삭제 아이콘이 잘 랜더링 되는 지 확인한다

 

이제 기능없는 UI 는 완성되었습니다

다음에는 기능 추가를 합니다

반응형