본문 바로가기

FrameWork/React

[React] Component / & 모든 부모 컴포넌트의 속성을 그대로 전달하기 위한 문법

  • …props 는 해당 컴포넌트로 모든 부모컴포넌트에서 전달된 속성들을 그대로 전달하기 위한 문법이다.
  • 이렇게 사용함으로써 Daycomponent 에서는 부모 컴포넌트에서 전달된 속성을 그대로 사용할 수 있다.
  • 직접 각 속성을 나열하려고 한다면, 새로운 속성이 추가될때마다 일일이 수정해야 하기 때문에 유지보수가 어려워진다. …props 를 사용하면 부모컴포넌트에서 어떤 속성이든 자동으로 전달되므로 코드의 유연성이 높아진다.
  • 그러나 특정한 속성이 있다면 해당 속성은 개별적으로 전달하는 것이 좋다.
// parents
  <Calendar
    dayComponent={(props) => (
      <DayComponent
        {...props}
        todos={todos} // 특정한 속성
        setSelectedDate={setSelectedDate} // 특정한 속성
      />
    )}
    style={styles.calenderWrap}
  />

// Children
function DayComponent({ date, state, todos, setSelectedDate }) {
  return (
    <View>
      <Text
        onPress={() => {
          // 날짜 선택시 호출 함수
          setSelectedDate(date.dateString);
        }}
        style={{
          textAlign: 'center',
          color: state === 'disabled' ? 'gray' : 'black',
        }}
      >
        {date.day}
      </Text>
      {/* calendar 에 각 날짜에 해당하는 TodoList 를 렌더링 */}
      {todos.map((item) => (
        <Text key={item.id} style={styles.todoText}>
          {date.dateString === item.date ? <Text>{item.text}</Text> : null}
        </Text>
      ))}
    </View>
  );
}

 

→ 수정 전 코드
import { useEffect, useState } from 'react';
import { StyleSheet, Text, View, Button } from 'react-native';
import { CalendarList, Calendar } from 'react-native-calendars';
import TodoList from './TodoList.js';
import AsyncStorage from '@react-native-async-storage/async-storage';

export default function App() {
  const [selectedDate, setSelectedDate] = useState(''); // 선택된 날짜 저장할 상태 변수
  const [todos, setTodos] = useState([]); // Todo 목록을 저장할 상태 변수

  //#region (비동기) 앱 시작시 AsyncStorage에서 데이터 불러오기
        ...
  //#endregion

  //#region Celendar (dayComponent) 각 날짜에 해당하는 컴포넌트 커스터마이징
  const renderDayComponent = ({ date, state }) => {
    return (
      <View>
        <Text
          onPress={() => {
            // 날짜 선택시 호출 함수
            setSelectedDate(date.dateString);
          }}
          style={{
            textAlign: 'center',
            color: state === 'disabled' ? 'gray' : 'black',
          }}
        >
          {date.day}
        </Text>
        {/* calendar 에 각 날짜에 해당하는 TodoList 를 렌더링 */}
        {todos.map((item) => (
          <Text key={item.id} style={styles.todoText}>
            {date.dateString === item.date ? <Text>{item.text}</Text> : null}
          </Text>
        ))}
      </View>
    );
  };
  //#endregion

  return (
    <View style={styles.container}>
      {/* 달력 컴포넌트 */}
      <Calendar dayComponent={renderDayComponent} style={styles.calenderWrap} />

      <Text style={styles.selectedDateText}>SelectedDate : {selectedDate}</Text>

      {/* TodoList 컴포넌트에 필터링된 Todo 목록과 추가 함수 전달 */}
      <TodoList
        onAddTodo={addTodo}
        todos={filteredTodos}
        onDeleteTodo={deleteTodo}
      />
    </View>
  );
}

const styles = StyleSheet.create({
...
});

 

→ 수정 후

[ DayComponent.js]

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

function DayComponent({ date, state, todos, setSelectedDate }) {
  return (
    <View>
      <Text
        onPress={() => {
          // 날짜 선택시 호출 함수
          setSelectedDate(date.dateString);
        }}
        style={{
          textAlign: 'center',
          color: state === 'disabled' ? 'gray' : 'black',
        }}
      >
        {date.day}
      </Text>
      {/* calendar 에 각 날짜에 해당하는 TodoList 를 렌더링 */}
      {todos.map((item) => (
        <Text key={item.id} style={styles.todoText}>
          {date.dateString === item.date ? <Text>{item.text}</Text> : null}
        </Text>
      ))}
    </View>
  );
}

const styles = StyleSheet.create({
  dayContainer: {
    flex: 1,
    margin: 10,
    alignItems: 'center',
    justifyContent: 'center',
  },
  todoText: {}, // Todo 스타일 추가
});

export default DayComponent;

[ App.js ]

import { useEffect, useState } from 'react';
import { StyleSheet, Text, View, Button } from 'react-native';
import { CalendarList, Calendar } from 'react-native-calendars';
import TodoList from './TodoList.js';
import AsyncStorage from '@react-native-async-storage/async-storage';
import DayComponent from './component/DayComponent.js';

export default function App() {
  const [selectedDate, setSelectedDate] = useState(''); // 선택된 날짜 저장할 상태 변수
  const [todos, setTodos] = useState([]); // Todo 목록을 저장할 상태 변수

  //#region (비동기) 앱 시작시 AsyncStorage에서 데이터 불러오기
    ...
  //#endregion

  //#region 앱이 시작될때 오늘 날짜로 선택한 날짜를 지정
  useEffect(() => {
    const todayDate = new Date().toISOString().split('T')[0];
    setSelectedDate(todayDate);
  }, []);
  //#endregion

  //#region Todo 추가
    ...
  //#region Todo 삭제
    ...

  // 선택한 날짜와 todo 의 날짜가 일치한 것만 필터링
  const filteredTodos = todos.filter((todo) => todo.date === selectedDate);

  return (
    <View style={styles.container}>
      {/* 달력 컴포넌트 */}

      <Calendar
        dayComponent={(props) => (
          <DayComponent
            {...props}
            todos={todos}
            setSelectedDate={setSelectedDate}
          />
        )}
        style={styles.calenderWrap}
      />

      <Text style={styles.selectedDateText}>SelectedDate : {selectedDate}</Text>

      {/* TodoList 컴포넌트에 필터링된 Todo 목록과 추가 함수 전달 */}
      <TodoList
        onAddTodo={addTodo}
        todos={filteredTodos}
        onDeleteTodo={deleteTodo}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  dayContainer: {
    flex: 1,
    margin: 10,
    alignItems: 'center',
    justifyContent: 'center',
  },

  container: {
    flex: 1,
    marginTop: '15%',
    // backgroundColor: '#000000',
    width: 'auto',
    borderWidth: 4,
    borderColor: '#ff0000',
  },

  calenderWrap: {
    // backgroundColor :'transparent',
  },

  selectedDateText: {},
});