// theme.js
export const theme = {
background: '#111111',
itemBackground: '#333333',
main: '#778bdd',
text: '#eeeeee',
done: '#666666',
};
// App.js
export default function App() {
return (
<ThemeProvider theme={theme}>
<Container>
<Text>ToDo</Text>
<StatusBar style="auto" />
</Container>
</ThemeProvider>
);
}
// App.js
const Container = styled.View`
flex: 1;
background-color: ${({ theme }) => theme.background};
align-items: center;
justify-content: center;
`;
// 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>
);
}
// 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,
};
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,
};
// 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>
);
}
// 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;
// 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>
);
}