To-Do App (1)

Sang heon lee·2022년 2월 14일
0

1. 프로젝트 준비

  • 공통으로 사용할 스타일 코드 작성
// theme.js
export const theme = {
  background: '#111111',
  itemBackground: '#333333',
  main: '#778bdd',
  text: '#eeeeee',
  done: '#666666',
};
  • ThemeProvider 사용하여 공용 스타일 코드 적용
// App.js
export default function App() {
  return (
    <ThemeProvider theme={theme}>
      <Container>
        <Text>ToDo</Text>
        <StatusBar style="auto" />
      </Container>
    </ThemeProvider>
  );
}
  • ThemeProvider 사용하여 스타일 코드 불러오기
// App.js
const Container = styled.View`
  flex: 1;
  background-color: ${({ theme }) => theme.background};
  align-items: center;
  justify-content: center;
`;

2. Title 만들기

// App.js
const Container = styled.SafeAreaView`
  flex: 1;
  background-color: ${({ theme }) => theme.background};
  align-items: center;
  justify-content: flex-start;
`;

// App.js
const Title = styled.Text`
  font-size: 40px;
  font-weight: 600;
  color: ${({ theme }) => theme.main};
  width: 100%;
  align-items: flex-end;
  padding: 0 20px;
`;

export default function App() {
  return (
    <ThemeProvider theme={theme}>
      <Container>
        <Title>ToDo List</Title>
        <StatusBar
          backgroundColor={theme.background}
          barStyle="light-content"
        />
      </Container>
    </ThemeProvider>
  );
}

3. Input 컴포넌트 만들기 - 디자인

  • Input 컴포넌트 만들기
  • CSS 코드 작성
  • 어느 핸드폰에서나 좌우 20px씩 남기고 컴포넌트 창 와이드를 지정하기 위하여 Dimensions 또는 useWindowDimensions 사용

4. Input 컴포넌트 만들기 - 상세설정

  • Input 컴포넌트 기능 코드 작성
// App.js
export default function App() {
  const [newTask, setNewTask] = useState('');

  const addTask = () => {
    alert(newTask);
    setNewTask('');
  };

  return (
    <ThemeProvider theme={theme}>
      <Container>
        <StatusBar
          backgroundColor={theme.background}
          barStyle="light-content"
        />
        <Title>ToDo List</Title>
        <Input
          placeholder="+ Add a Task"
          value={newTask}
          onChangeText={text => setNewTask(text)}
          onSubmitEditing={addTask}
        ></Input>
      </Container>
    </ThemeProvider>
  );
}

// Input.js
const Input = ({ placeholder, value, onChangeText, onSubmitEditing }) => {
  // const width = Dimensions.get('window').width;
  const width = useWindowDimensions().width;
  return (
    <StyledInput
      width={width}
      placeholder={placeholder}
      maxLength={50}
      autoCapitalize="none" // 자동 대문자 기능
      autoCorrect={false} // 자동 수정 기능
      returnKeyType="done" // 완료(엔터) 버튼에 done 으로 표시
      keyboardAppearance="dark" // 자판 색상
      value={value}
      onChangeText={onChangeText}
      onSubmitEditing={onSubmitEditing} // 제출 토글시 작동 함수
    ></StyledInput>
  );
};

// props 속성 설정
Input.propTypes = {
  placeholder: propTypes.string,
  value: propTypes.string.isRequired,
  onChangeText: propTypes.func.isRequired,
  onSubmitEditing: propTypes.func.isRequired,
};

5. IconButton 컴포넌트

  • assets 폴더 -> icons 폴더에 사용할 이미지 넣기

  • 사용할 이미지 코드 작성

// /src/components/icons.js
import Check from '../../assets/icons/check.png';
import Uncheck from '../../assets/icons/uncheck.png';
import Delete from '../../assets/icons/delete.png';
import Edit from '../../assets/icons/edit.png';

export const icons = {
  check: Check,
  uncheck: Uncheck,
  edit: Edit,
  delete: Delete,
};
  • IconButton 컴포넌트 만들기
// components/IconButton.js
import react, { useState } from 'react';
import styled from 'styled-components/native';
import { TouchableOpacity, View } from 'react-native';
import propTypes from 'prop-types';
import { icons } from './icons';

const Icon = styled.Image`
  width: 30px;
  height: 30px;
  margin: 10px;
  tint-color: ${({ theme }) => theme.text};
`;

const IconButton = ({ icon, onPress }) => {
  return (
    <TouchableOpacity onPress={onPress}>
      <View>
        <Icon source={icon}></Icon>
      </View>
    </TouchableOpacity>
  );
};

IconButton.proptype = {
  icon: propTypes.oneOf(Object.values(icons)).isRequired,
  onPress: propTypes.func,
};

export default IconButton;
  • 여러 아이콘 만들기
// App.js

import IconButton from './components/IconButton';
import { icons } from './components/icons.js';
...
return (
    <ThemeProvider theme={theme}>
      <Container>
        <StatusBar
          backgroundColor={theme.background}
          barStyle="light-content"
        />
        <Title>ToDo List</Title>
        <Input
          placeholder="+ Add a Task"
          value={newTask}
          onChangeText={text => setNewTask(text)}
          onSubmitEditing={addTask}
        ></Input>
        <IconButton icon={icons.check} onPress={() => alert('check')} />
        <IconButton icon={icons.uncheck} onPress={() => alert('uncheck')} />
        <IconButton icon={icons.edit} onPress={() => alert('edit')} />
        <IconButton icon={icons.delete} onPress={() => alert('delete')} />
      </Container>
    </ThemeProvider>
  );
}

6. Task 컴포넌트

  • Task 컴포넌트 작성
// components/Task.js
import react, { useState } from 'react';
import styled from 'styled-components/native';
import propTypes from 'prop-types';
import IconButton from './IconButton';
import { icons } from './icons';

const Container = styled.View`
  flex-direction: row;
  align-items: center;
  background-color: ${({ theme }) => theme.itemBackground};
  border-radius: 10px;
  padding: 5px;
  margin: 3px 0;
`;
const Contents = styled.Text`
  flex: 1;
  font-size: 24px;
  color: ${({ theme }) => theme.text};
`;

const Task = ({ text }) => {
  return (
    <Container>
      <IconButton icon={icons.uncheck} />
      <Contents>{text}</Contents>
      <IconButton icon={icons.edit} />
      <IconButton icon={icons.delete} />
    </Container>
  );
};

Task.propTypes = {
  text: propTypes.string.isRequired,
};

export default Task;
  • Task 를 담을 List 컴포넌트 만들기 (스크롤바 생기게)

// App.js
const List = styled.ScrollView`
  flex: 1;
  width: ${({ width }) => width - 40}px;
`;
......
return (
    <ThemeProvider theme={theme}>
      <Container>
        <StatusBar
          backgroundColor={theme.background}
          barStyle="light-content"
        />
        <Title>ToDo List</Title>
        <Input
          placeholder="+ Add a Task"
          value={newTask}
          onChangeText={text => setNewTask(text)}
          onSubmitEditing={addTask}
        ></Input>
        <List width={width}>
          <Task text="reack native"></Task>
          <Task text="reack native"></Task>
          <Task text="reack native"></Task>
          <Task text="reack native"></Task>
          <Task text="reack native"></Task>
          <Task text="reack native"></Task>
          <Task text="reack native"></Task>
          <Task text="reack native"></Task>
          <Task text="reack native"></Task>
          <Task text="reack native"></Task>
          <Task text="reack native"></Task>
          <Task text="reack native"></Task>
          <Task text="reack native"></Task>
          <Task text="reack native"></Task>
          <Task text="reack native"></Task>
          <Task text="reack native"></Task>
        </List>
      </Container>
    </ThemeProvider>
  );
}
profile
개초보

0개의 댓글