[ToyProject-Todomate] ํˆฌ๋‘๋ฉ”์ดํŠธ ํด๋ก  ํ”„๋กœ์ ํŠธ 23

2022. 1. 6. 23:47ใ†WEB Dev/ToyProject

728x90


๐Ÿ”ท CloneTodo โ˜‘ - Todomate Clone Project  |  Team CloneMate

 

CloneTodo : ๋งŽ์€ ์‚ฌ๋žŒ๋“ค์ด ์‚ฌ๋ž‘ํ•˜๋Š” ํˆฌ๋‘๋ฉ”์ดํŠธ๋ฅผ ํด๋ก ํ•˜์—ฌ ์›น ์„œ๋น„์Šค๋ฅผ ๋ฐฐํฌํ•ด๋ณด๋Š” ํ”„๋กœ์ ํŠธ

 


 

์˜ค๋Š˜์€ ์ˆ˜์ •๋ถ€๋ถ„์„ ๋งŒ๋“ค ์ฐจ๋ก€! ์‹ค์ œ๋กœ ์ฑ…์—์„œ ๋„์›€์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” ๋ถ€๋ถ„์€ ์„œ๋ฒ„ ์—ฐ๊ฒฐ์ด๋ผ๊ณ  ์ƒ๊ฐํ•œ๋‹ค.

์ฑ…์—์„œ๋Š” ์—„์ฒญ ๋‹จ์ˆœํ•œ ์•ฑ์„ ๋งŒ๋“ค๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค ใ… ใ… 

์–ด์จŒ๋“  ํˆฌ๋‘ ๋“ฑ๋ก, ์ˆ˜์ •, ์‚ญ์ œ๊ฐ€ ๊ธฐ๋Šฅ์˜ ๋Œ€๋ถ€๋ถ„์ด๋‹ˆ๊นŒ ...

 

 

์ˆ˜์ •์—๋Š” ๋‘ ๊ฐ€์ง€๊ฐ€ ์žˆ๋‹ค.

์ฒซ๋ฒˆ์งธ๋Š” ํˆฌ๋‘ ์ƒํƒœ ๋ณ€ํ™”๋‹ค.

ํˆฌ๋‘์— ์ฒดํฌ๋ฅผ ํ•˜๋ฉด ํ•  ์ผ์„ ์™„๋ฃŒํ•œ ์ƒํƒœ์ด๊ธฐ ๋•Œ๋ฌธ์— items state์˜ done ๊ฐ’์ด true๊ฐ€ ๋˜๊ฒŒ ํ•˜๋Š” ๊ฒƒ๊ณผ

์ด๋ฏธ ๋“ฑ๋กํ•œ ํˆฌ๋‘๋ฅผ ์ˆ˜์ •ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

 

๊ทธ๋ฆฌ๊ณ  ๋˜ ํ•œ ๊ฐ€์ง€๋Š” ์ด๋ฏธ ๋“ฑ๋กํ•œ ํˆฌ๋‘๋ฅผ ํด๋ฆญํ•˜๋ฉด ๋‚ด์šฉ์„ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋Š” ๋‹จ๊ณ„๋‹ค.

์ด ๋‹จ๊ณ„๊ฐ€ ์ข€ ๋ณต์žกํ•˜๋‹ค.

 

 

 

์šฐ์„  ๋“ฑ๋กํ•œ ๋ชฉํ‘œ์— readOnly ๋ผ๋Š” props๋กœ ์ƒํƒœ๋ฅผ ํ‘œํ˜„ํ•ด์ค˜์•ผ ํ•˜๋Š”๋ฐ, ์ฑ…์˜ ์ฝ”๋“œ๋ฅผ ํ•จ์ˆ˜ํ˜•์œผ๋กœ ์–ด๋–ป๊ฒŒ ๋ณ€ํ™˜ํ•ด์•ผ ํ•˜๋Š”์ง€ ๊ฐ์ด ์•ˆ์˜จ๋‹ค. 

 

  let goalItems = props.goal;
  let addGoal = props.addGoal;
  let deleteGoal = props.deleteGoal;

    function deleteEventHandler(e) {
      console.log( 'id : ',  e.target.id)
      deleteGoal(e.target.id, goalItems)
    }

 

 

์œ„์™€ ๊ฐ™์ด ๋งŒ๋“ค์–ด๋’€๋˜ props ๋“ค์ธ๋ฐ..

์ฑ…์—์„œ๋Š” 

 

 

constructor(props) {
	super(props)
    this.state = { item : props.item, readOnly : true };
    this.delete = props.delete;
}

 

 

๊ทธ๋Ÿผ readOnly ๋ณ€์ˆ˜๋ฅผ ๋”ฐ๋กœ ์ค˜์•ผ ํ•˜๋Š”๊ฑด์ง€.. goalItems๋กœ ๋งŒ๋“  props ๋ฅผ ๊ฐ์ฒด๋กœ ๋งŒ๋“ค์–ด์•ผ ํ•˜๋Š”๊ฑด์ง€...

์™ ์ง€ ๋ณ„๋„๋กœ ๋ณ€์ˆ˜๋กœ ๋งŒ๋“ค์–ด ์ค˜์•ผ๊ฒ ์ง€..?

์•„๋‹ˆ state์— ์ถ”๊ฐ€ํ•ด๊ฐ€์ง€๊ณ  props๋กœ ๋งŒ๋“ค์–ด์ค˜์•ผํ•˜๋Š”๊ฑฐ๊ฒ ์ง€..?

์ด ์ •๋„ ๊ณต๋ถ€ํ–ˆ์œผ๋ฉด ์ฐฐ๋–ก๊ฐ™์ด ์•Œ์•„๋“ค์–ด์•ผํ•˜๋Š”๋ฐ...

 

 

์ €๋ฒˆ์— ๋งŒ๋“  goal state ์•„๋ž˜์— readOnly state๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค.

 

 

  let [readOnly, readOnlyChange] = useState(true)

 

 

๊ทธ๋ฆฌ๊ณ  ๋‹ค์‹œ Goals ์ปดํฌ๋„ŒํŠธ๋กœ ๋„˜๊ฒจ์ฃผ์—ˆ๋‹ค.

 

 

<Goals goal={goal.items} addGoal={addGoal} deleteGoal={deleteGoal} readOnly={readOnly}  />

 

 

๊ทธ๋ฆฌ๊ณ  offReadOnlyMode ๋ผ๋Š” ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด ์ค€๋‹ค.

 

 

   // readOnly ์ƒํƒœ ๋ณ€๊ฒฝ ํ•จ์ˆ˜
   function offReadOnlyMode(){
    console.log("Event!", readOnly)
    readOnlyChange(readOnly = false)
  }

 

 

์ด๊ฒƒ๋“ค์„ ๋˜ props๋กœ ๋‹ค ๋„˜๊ฒจ์ค€๋‹ค.

 

 

 

<Goals goal={goal.items} addGoal={addGoal} 
deleteGoal={deleteGoal} readOnly={readOnly} readOnlyChange={offReadOnlyMode}  />

 

 

๊ทธ๋ฆฌ๊ณ  Goals.js์—์„œ props๋กœ ๋ฐ›์•„์™€์„œ ๋ณ€์ˆ˜์— ๋‹ด๊ณ ...

 

  let readOnly = props.readOnly;
  let readOnlyChange = props.readOnlyChange;

 

inputBase์— readOnly์™€ onClick ์ด๋ฒคํŠธ๋กœ ํ•จ์ˆ˜๋ฅผ ๋„˜๊ฒจ์ค€๋‹ค.

 

 

 <InputBase
   inputProps={{ "aria-label": "naked", readOnly: readOnly, }}
   onClick={readOnlyChange}
   type="text"
   id={item.id}
   name={item.id}
   value={item.title}
   multiline={true}
   fullWidth={true}
 />

 

 

์ด๋ ‡๊ฒŒ ์ž‘์„ฑํ•ด์ฃผ๋‹ˆ ๋ชฉํ‘œ๋ฅผ ํด๋ฆญํ–ˆ์„ ๋•Œ, ์ฝ˜์†”์— readOnly๊ฐ€ false๋กœ ๋ณ€ํ–ˆ๋‹ค!

 

์ด์ œ ๋‹ค์‹œ enter๋ฅผ ๋ˆ„๋ฅด๋ฉด readOnly๋ฅผ true๋กœ ๋ฐ”๊ฟ”์ฃผ๋Š” ํ•จ์ˆ˜๋ฅผ ์ž‘์„ฑํ•œ๋‹ค.

์ด์ „์— ์ž‘์„ฑํ•œ enterKeyEventHandler์™€ ์œ ์‚ฌํ•˜๋‹ค.

 

 

  //readOnly ์ƒํƒœ true๋กœ ๋ณ€๊ฒฝ ํ•จ์ˆ˜
  function enterKeyEventHandler(e){
    if(e.key === 'Enter'){
      readOnlyChange(readOnly = true)
    }
  }

 

 

 

๊ทธ๋Ÿผ ์ด ํ•จ์ˆ˜๋ฅผ ๋‹ค์‹œ props๋กœ ๋ณด๋‚ด์ค€๋‹ค.

 

 

<Goals goal={goal.items} addGoal={addGoal} deleteGoal={deleteGoal} readOnly={readOnly} 
readOnlyChange={offReadOnlyMode} enterKeyEventHandler={enterKeyEventHandler} />

 

 

๋‹ค์‹œ Goals์—์„œ enterKeyEventHandler๋ฅผ ๋ฐ›์•„์ฃผ๊ณ  (์ด์ „์˜ enterKeyEventHandler ํ•จ์ˆ˜๋Š” GoalForm์— ์žˆ์Œ!)

onKeyPress๋กœ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด์ค€๋‹ค. 

 

 

<InputBase
  inputProps={{ "aria-label": "naked", readOnly: readOnly, }}
  onClick={readOnlyChange}
  onKeyPress={enterKeyEventHandler}
  type="text"
  id={item.id}
  name={item.id}
  value={item.title}
  multiline={true}
  fullWidth={true}
/>

 

 

 

์ด์ œ readOnly๋ฅผ ๋งŒ๋“ค์–ด์คฌ์œผ๋‹ˆ item์„ ์ˆ˜์ •ํ•ด๋ณด์ž.

 

 

์šฐ์„  ์ˆ˜์ • ํ•จ์ˆ˜๋ฅผ ์ž‘์„ฑํ•œ๋‹ค. state๊ฐ€ ์žˆ๋Š” ๊ณณ์—์„œ ์ž‘์„ฑํ•œ๋‹ค.

 

 //items state ์ˆ˜์ • ํ•จ์ˆ˜
  function editEventHandler(e){
    const thisItems = goal.items; // goal State ์›๋ณธ ์นดํ”ผ
    thisItems.title = e.target.value;
    goalChange({items: thisItems}); //goalChange๋ฅผ ์ด์šฉํ•ด state ๋ณ€๊ฒฝ
  }

 

 

์ด edit ํ•จ์ˆ˜๋ฅผ props๋กœ ์ „๋‹ฌํ•ด InputBase์— onChange๋กœ ์—ฐ๊ฒฐํ•œ๋‹ค.

 

 

<Goals goal={goal.items} addGoal={addGoal} deleteGoal={deleteGoal} 
readOnly={readOnly} readOnlyChange={offReadOnlyMode} 
enterKeyEventHandler={enterKeyEventHandler} editEventHandler={editEventHandler} />

 

  let goalItems = props.goal;
  let addGoal = props.addGoal;
  let deleteGoal = props.deleteGoal;
  let readOnly = props.readOnly;
  let readOnlyChange = props.readOnlyChange;
  let enterKeyEventHandler = props.enterKeyEventHandler;
  let editEventHandler = props.editEventHandler;

 

<InputBase
  inputProps={{ "aria-label": "naked", readOnly: readOnly, }}
  onClick={readOnlyChange}
  onKeyPress={enterKeyEventHandler}
  onChange={editEventHandler}
  type="text"
  id={item.id}
  name={item.id}
  value={item.title}
  multiline={true}
  fullWidth={true}
/>

 

 

 

์•„์ด๊ณ  ใ… ใ…  ์ž‘๋™์ด ์•ˆ๋œ๋‹ค....ใ… ใ… ใ… ใ… 

 

์šฐ์„ ์€ ๋งˆ๋ฌด๋ฆฌ๋กœ ์ฒดํฌ๋ฐ•์Šค๋ฅผ ํด๋ฆญํ•˜๋ฉด done state๊ฐ€ true๋กœ, ํด๋ฆญ๋˜์—ˆ์„ ๋•Œ, ํด๋ฆญ์„ ํ’€๋ฉด false๋กœ ๋ฐ”๋€Œ๋„๋ก ํ•ด๋ณธ๋‹ค.

 

  //์ฒดํฌ๋ฐ•์Šค ํด๋ฆญ ํ•จ์ˆ˜
  function checkboxEventHandler(e){
    const thisItems = goal.items;
    thisItems.done = !thisItems.done;
    goalChange({items: thisItems})
  }

 

 

์ด ํ•จ์ˆ˜๋ฅผ props๋กœ ๋ณด๋‚ด checkbox ์— ์—ฐ๊ฒฐํ•œ๋‹ค.

 

<Goals goal={goal.items} addGoal={addGoal} deleteGoal={deleteGoal} 
readOnly={readOnly} readOnlyChange={offReadOnlyMode} 
enterKeyEventHandler={enterKeyEventHandler} editEventHandler={editEventHandler}
checkboxEventHandler={checkboxEventHandler} />

 

 

import React from "react";
import { Checkbox, IconButton, InputBase, ListItem, ListItemText } from "@mui/material";
import GoalForm from "./GoalForm";
import { ListItemSecondaryAction } from "@material-ui/core";

export default function Goals(props) {
  console.log(props);
  let goalItems = props.goal;
  let addGoal = props.addGoal;
  let deleteGoal = props.deleteGoal;
  let readOnly = props.readOnly;
  let readOnlyChange = props.readOnlyChange;
  let enterKeyEventHandler = props.enterKeyEventHandler;
  let editEventHandler = props.editEventHandler;
  let checkboxEventHandler = props.checkboxEventHandler;


  //๋ชฉํ‘œ ์‚ญ์ œ ์ด๋ฒคํŠธํ•ธ๋“ค๋Ÿฌ ํ•จ์ˆ˜

    function deleteEventHandler(e) {
      console.log( 'id : ',  e.target.id)
      deleteGoal(e.target.id, goalItems)
    }

    
 

  return (
    <>
    <GoalForm addGoal={addGoal} />

        {
        goalItems.map((item, idx) => {
         
        return ( <ListItem className="goals-wrap" key={item.id} > { console.log('item: ', item) }
                    <Checkbox checked={item.done} onChange={checkboxEventHandler} />
                    <ListItemText>
                    <InputBase
                        inputProps={{ "aria-label": "naked", readOnly: readOnly, }}
                        onClick={readOnlyChange}
                        onKeyPress={enterKeyEventHandler}
                        onChange={editEventHandler}
                        type="text"
                        id={item.id}
                        name={item.id}
                        value={item.title}
                        multiline={true}
                        fullWidth={true}
                    />
                    </ListItemText>
                    <ListItemSecondaryAction>
                    <IconButton aria-label="Delete Todo" id={item.id} 
                    onClick={deleteEventHandler} sx={{ fontSize: '14px' }}>
                        ์‚ญ์ œ
                    </IconButton>
                </ListItemSecondaryAction>
                </ListItem>
                );
            })
        }
    </>
  );
}

 

์•ˆ๋œ๋‹ค...

 

 

์™ ์ง€.. ์‚ญ์ œ ๊ตฌํ˜„ํ–ˆ์„ ๋•Œ์˜ ๋ฌธ์ œ์ฒ˜๋Ÿผ ํด๋ž˜์Šคํ˜•์—์„œ๋Š” this๋ฅผ ์จ์„œ ์ด๋ฒคํŠธ๋ฅผ ์žก์•„๋‚ด๋Š”๋ฐ this๊ฐ€ ๋น ์ ธ๋ฒ„๋ฆฌ๋ฉด์„œ ์–ด๋–ค๊ฒŒ ํด๋ฆญ๋˜์—ˆ๋Š”์ง€ ์ œ๋Œ€๋กœ ์•ˆ์žกํ˜€์„œ ๊ทธ๋Ÿฐ ๊ฒƒ ๊ฐ™๋‹ค.

(e)๊ฐ€ ์žˆ๋Š”๋ฐ๋„...

 

๋‘˜ ๋‹ค ๋น„์Šทํ•œ ๋ฌธ์ œ์ธ ๊ฒƒ ๊ฐ™์œผ๋‹ˆ ๋‚˜์ค‘์— ์ˆ˜์ •ํ•ด์•ผ๊ฒ ๋‹ค ใ… ใ… ใ… ใ… ใ… 

 

 

์ด๊ฑฐ ํ•ด๊ฒฐํ•˜๋ฉด ์ž…๋ ฅ ๋ถ€๋ถ„๊ณผ ์ถœ๋ ฅ ๋ถ€๋ถ„ ํ™”๋ฉด์„ ๋”ฐ๋กœ ๋ถ„๋ฆฌ์‹œ์ผœ์•ผ๊ฒ ์Œ!!

 

 

 

 

728x90